From: "sawa (Tsuyoshi Sawada)" <noreply@...> Date: 2022-10-19T04:19:11+00:00 Subject: [ruby-core:110417] [Ruby master Feature#19069] Default value assignment with `Hash.new` in block form Issue #19069 has been updated by sawa (Tsuyoshi Sawada). @nobu (Nobuyoshi Nakada) I interpret that your concern is that the hash will grow endlessly by random referencing (unintentionally or by an attack). I have two possible alternative modifications to the proposal for that. 1. Warn when a block without parameter signature `Hash.new{"foo"}` is used. 2. Forget about looking at the block arity, and explicitly control the behavior as below: ```rb h1 = Hash.new{|h, k| "foo"} h2 = Hash.new{"foo"} h3 = Hash.new(assign: true){|h, k| "foo"} h4 = Hash.new(assign: true){"foo"} h1[:a] # => "foo" h2[:a] # => "foo" h3[:a] # => "foo" h4[:a] # => "foo" h1 # => {} h2 # => {} h3 # => {:a=>"foo"} h4 # => {:a=>"foo"} ``` Option 2 will decrease the usefulness of the proposal a little bit for the use case mentioned in the proposal, but writing ` Hash.new(assign: true){"foo"}` may still be a bit better than writing ` Hash.new{|h, k| h[k] = "foo"}`. ---------------------------------------- Feature #19069: Default value assignment with `Hash.new` in block form https://bugs.ruby-lang.org/issues/19069#change-99729 * Author: sawa (Tsuyoshi Sawada) * Status: Open * Priority: Normal ---------------------------------------- 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). ```rb 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: ```rb 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. -- https://bugs.ruby-lang.org/ Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe> <http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>