Project

General

Profile

Bug #16498

Updated by sawa (Tsuyoshi Sawada) over 4 years ago

The following is unexpected for me. most minimal reproductions I found, in Ruby 2.7: 

 ```ruby ``` 
 $ ruby -e "puts Hash.new { }.transform_values { }.default }.default" 
 # => #<Proc:0x000055eecda01510 -e:1> 
 $ ruby -e "puts Hash.new { }.transform_values { }[:any] }[:any]" 
 # => #<Proc:0x0000563a12e35510 -e:1> 
 $ ruby -e "puts Hash.new { :default }.transform_values { }[:any][] }[:any][]" 
 # => :default default 
 ``` 

 That was unexpected for me, because I did not think a `default_proc` default_proc would turn into a default. The previous behaviour in 2.6 was that the default would be `nil`, nil, so this is new in 2.7. But I didn't see this get mentioned in the 2.7 NEWS. May I learn of the proper use for this and/or whether it is intentional? 

 If you wonder when we might see something like this, I had found it with code similar in idea to the following: 

 ```ruby ``` 
 weights = Hash.new { |h, k| h[k] = [] } 
 weights[:apple] << 1 
 weights[:apple] << 2 

 prices = weights.transform_values { :arbitrary } 

 puts (prices[:mango] || [])[0] || "We're all out of mangoes today" 
 ``` 

 ``` 
 in $ ruby hash_default.rb 
 Traceback (most recent call last): 
	 1: from hash_default.rb:7:in `<main>' 
 hash_default.rb:1:in `block in <main>': undefined method `[]=' for 0:Integer (NoMethodError) 
 Did you mean?    [] 
 ``` 

 That was quite a confusing error message. It message, since it took a while to realise why `[]=` was has gotten called on `0`. 0... 

 We also cannot fix this by using `dig` (`puts prices.dig(:mango, 0) || "We're all out of mangoes today"`) today"`), because then, then we would get: 

 ``` 
 in Traceback (most recent call last): 
	 1: from hash_default.rb:7:in `<main>' 
 hash_default.rb:7:in `dig': Proc does not have #dig method (TypeError) 
 ``` 

Back