From: daniel@...42.com Date: 2019-10-22T17:41:15+00:00 Subject: [ruby-core:95470] [Ruby master Bug#16270] Strange behavior on Hash's #each and #select method. Issue #16270 has been updated by Dan0042 (Daniel DeLorme). Of all Hash methods, only select/reject/select!/reject!/keep_if/delete_if have that behavior. That's fairly inconsistent, but more importantly it doesn't seem like this inconsistency is on purpose. There is no test for this case in test/ruby/test_hash.rb. I tried changing `rb_yield_values(2` to `rb_yield(rb_assoc_new(` and I got only one failure in the specs, in test_delete_if, because of `h.delete_if {|*a|` where `*a` becomes `[[1,"one"]]` instead of `[1,"one"]`. And this is more related to #16166 than the current issue. ---------------------------------------- Bug #16270: Strange behavior on Hash's #each and #select method. https://bugs.ruby-lang.org/issues/16270#change-82240 * Author: zw963 (Wei Zheng) * Status: Closed * Priority: Normal * Assignee: * Target version: * ruby -v: 2.6.3 * Backport: 2.5: UNKNOWN, 2.6: UNKNOWN ---------------------------------------- The following is some example code: ``` ruby sample_hash = { "246" => { "price" => "8000", "note" => "" }, "247" => { "price" => "8000", "note" => "" }, "248" => { "price" => "8000", "note" => "" } } sample_hash.each {|e| p e} # The following is p's output content. We can see that e is a hash element, and is converted into an array object. # This is expected behavior maybe. Anyway, a hash is the same as a nested array. ["246", {"price"=>"8000", "note"=>""}] ["247", {"price"=>"8000", "note"=>""}] ["248", {"price"=>"8000", "note"=>""}] sample_hash.select {|e| p e } # Wired(?). Why is e's output this time different from each? "246" "247" "248" ``` The following is source code for **each** ```c static VALUE rb_hash_each_pair(VALUE hash) { RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size); if (rb_block_arity() > 1) rb_hash_foreach(hash, each_pair_i_fast, 0); else rb_hash_foreach(hash, each_pair_i, 0); return hash; } ``` The following is source code for **select** ```c VALUE rb_hash_select(VALUE hash) { VALUE result; RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size); result = rb_hash_new(); if (!RHASH_EMPTY_P(hash)) { rb_hash_foreach(hash, select_i, result); } return result; } ``` I don't understand C well, and don't know why the above two Hash methods lack consistency. But I think it confuses me a little. -- https://bugs.ruby-lang.org/ Unsubscribe: