Feature #19069
closedDefault value assignment with `Hash.new` in block form
Description
This is a spin-out from #19063, and is a recapture of my comment https://bugs.ruby-lang.org/issues/19063#note-15.
I propose to change the behavior of Hash.new
when it takes a block with its parameter signature absent. In such case, the evaluated value of the block should be assigned to the hash with the missing key in question (h3
below). When the block does take parameters, then the behavior should remain as is now (h1
, h2
below).
h1 = Hash.new{|h, k| h[k] = "foo"}
h2 = Hash.new{|h, k| "foo"}
h3 = Hash.new{"foo"}
h1[:a] # => "foo"
h2[:a] # => "foo"
h3[:a] # => "foo"
h1 # => {:a=>"foo"}
h2 # => {}
h3 # => {:a=>"foo"}
This will solve a few problems. First, as discussed in #19063, many users make the mistake of writing Hash.new([])
when they actually mean Hash.new{|h, k| h[k] = []}
, and I suspect this is partially due to the fact that the block {|h, k| h[k] = []}
is too long, and the users are tempted to avoid writing so. With the proposed feature introduced, the users will be encouraged to naturally write the correct form Hash.new{[]}
.
Second, some of the more advanced users than those mentioned above still make the mistake of writing Hash.new{foo}
when they actually mean Hash.new{|h, k| h[k] = foo}
, and the current proposal is to let them actually be equivalent.
Third, this will resemble a similar construct Array.new(5){[]}
and they will make a good parallel.
Indeed, there are situations where the intended behavior is to just run a routine without assigning a new key-value pair to the hash. Examples of current code may be as follows:
h4 = Hash.new{some_routine_to_take_care_of_the_missing_key_situation}
h5 = Hash.new{raise WrongKeyBlahBlahError}
Such blocks would need to be prepended by a parameter signature |h, k|
in order to avoid unwanted results. I do not think such transition would be a huge pain.