From: "jeremyevans0 (Jeremy Evans)" Date: 2022-11-18T18:57:38+00:00 Subject: [ruby-core:110816] [Ruby master Bug#19113] Inconsistency in retention of compare_by_identity flag in Hash methods Issue #19113 has been updated by jeremyevans0 (Jeremy Evans). headius (Charles Nutter) wrote in #note-6: > Even though it's a "new Hash", it is supposed to be populated with "the given objects". If losing identity comparison means some keys don't get populated, I would consider that broken. If you turn the hash into an array, you have the same `given objects`, but different results: ```ruby h = {'a'=>1}.compare_by_identity h['a'] = 2 Hash[h] # {'a'=>1, 'a'=>2}.compare_by_identity Hash[h.to_a] # {'a'=>2} ``` Not respecting the compare_by_identity flag (as my PR does) would make `Hash[h] == Hash[h.to_a]`. I would say that `populated with the given objects` does not imply `resulting in the same set of keys.` Also, `given objects` (not `given object`) implies it looks at the content of the hash, but not the hash object itself (hence why default value/proc is not copied). Here's the pseudocode I would consider based on the documentation: ```ruby # new hash output_hash = {} # populated with the given objects input_hash_or_array.each do |k, v| output_hash[k] = v end output_hash ``` There are certainly valid arguments for both sides, so we'll have to see what @matz decides. ---------------------------------------- Bug #19113: Inconsistency in retention of compare_by_identity flag in Hash methods https://bugs.ruby-lang.org/issues/19113#change-100174 * Author: jeremyevans0 (Jeremy Evans) * Status: Open * Priority: Normal * ruby -v: ruby 3.2.0dev (2022-11-07T17:29:28Z master 9001e53e68) [x86_64-openbsd7.2] * Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN ---------------------------------------- `Hash.[]` and `Hash.ruby2_keywords_hash` retain the compare_by_identity flag for non-empty hashes, but do not retain it for empty hashes: ```ruby hs = [{}.compare_by_identity, {:a=>1}.compare_by_identity] hs.map{|h| Hash[h].compare_by_identity?} # => [false, true] hs.map{|h| Hash.ruby2_keywords_hash(h).compare_by_identity?} # => [false, true] ``` This inconsistency seems like a bug. `Hash#compact` always drops the compare_by_identity flag, but it is documented as returning a copy of self, implying the compare_by_identity flag is kept (since #dup and #clone retain the flag). ```ruby {}.compare_by_identity.compact.compare_by_identity? # => false ``` I'm not sure whether is a bug, because it is consistent, but I think retaining the flag makes more sense. I'll try to work on a fix for both of these issues tomorrow. -- https://bugs.ruby-lang.org/ Unsubscribe: