From: "Eregon (Benoit Daloze)" Date: 2022-08-05T17:57:22+00:00 Subject: [ruby-core:109426] [Ruby master Feature#18950] Hash#slice fails to copy default block Issue #18950 has been updated by Eregon (Benoit Daloze). This could lead to surprising behavior, e.g.: ```ruby cache = Hash.new { |h,k| cache[k] = {} } cache[:a] sliced = cache.slice(:a) sliced[:foo] # => actually mutates cache with this proposal ``` Yes this would not be a problem if `h[k] = {}` is used as the block, but that's not always the case. Also if we start copying the default value/block, it seems a slippery slope e.g. to copy instance variables, class, and other state too, which all seem not desirable (and even were decided against recently). OTOH I guess copying `compare_by_identity` does make sense. ---------------------------------------- Feature #18950: Hash#slice fails to copy default block https://bugs.ruby-lang.org/issues/18950#change-98581 * Author: RubyBugs (A Nonymous) * Status: Open * Priority: Normal ---------------------------------------- An intense weekend debugging session discovered the following root cause of a bug: `Hash#slice` returns a new Hash, which has no default block set, even if the source Hash did have a default block set. Simplified code to reproduce: ``` ruby # Default to an empty hash for all accessed keys hash_with_default = Hash.new { |h, k| h[k] = {} } # => {} hash_with_default[:a] # => {} hash_with_default[:b] # => {} hash_with_default # => {:a=>{}, :b=>{}} # Later, use Hash#slice hash_sliced = hash_with_default.slice(:a, :b) # => {:a=>{}, :b=>{}} # Finally, access a new key hash_sliced[:c] # => nil # Error -- that was expected to call the default block raise "No default value" unless hash_sliced[:c] == {} ``` -- https://bugs.ruby-lang.org/ Unsubscribe: