+ 7

Can someone explain the following code in Ruby?

I have this code: h = Hash.new{ 1 2 3 } The following statements all results in printing out 3: puts h [0] puts h [1] puts h [2] puts h [3] > 3 Have tried Google but am not sure what to search for. So you guys are my last hope.

17th May 2018, 8:09 AM
Adam Aksu
Adam Aksu - avatar
8 Réponses
+ 3
Hashes have a thing called a default_proc, which is simply a proc that Ruby runs when you try to access a hash key that doesn't exist. This proc receives both the hash itself and the target key as parameters. You can set a Hash's default_proc at any time. Passing a block parameter to Hash.new simply allows you to initialize a Hash and set its default_proc in one step: h = Hash.new h.default_proc = proc{ |hash, key| hash[key] = 'foo' } # The above is equivalent to: h = Hash.new{ |hash, key| hash[key] = 'foo' } We can also access the default proc for a hash by calling h.default_proc. Knowing this, and knowing that the ampersand (&) allows a proc passed as a normal parameter to be treated as a block parameter, we can now explain how this code works: cool_hash = Hash.new{ |h, k| h[k] = Hash.new(&h.default_proc) } The block passed to Hash.new will be called when we try to access a key that doesn't exist. This block will receive the hash itself as h, and the key we tried to access as k. We respond by setting h[k](that is, the value of the key we're trying to access) to a new hash. Into the constructor of this new hash, we pass the "parent" hash's default_proc, using an ampersand to force it to be interpreted as a block parameter. This is the equivalent of doing the following, to an infinite depth: cool_hash = Hash.new{ |h, k| h[k] = Hash.new{ |h, k| h[k] = Hash.new{ ... } } } The end result is that the key we tried to access was initialized to a new Hash, which itself will initialize any "not found" keys to a new Hash, which itself will have the same behavior, etc. It's hashes all the way down. Source: stackoverflow.com/questions/20158213/ruby-hash-creating-a-default-value-for-non-existing-elements
17th May 2018, 10:45 AM
Nikita Semenov
Nikita Semenov - avatar
+ 2
Should this code when no key is defined result in the default value is set to 3, that is the last value?
17th May 2018, 8:36 AM
Adam Aksu
Adam Aksu - avatar
+ 2
Hashes have a default value that is returned when accessing keys that do not exist in the hash. If no default is set nil is used. You can set the default value by sending it as an argument to ::new: grades = Hash.new(0)
17th May 2018, 9:08 AM
Nikita Semenov
Nikita Semenov - avatar
+ 2
[user id="3613244"]Nikita Semenov www.taskker.club[/user] I think the hash's default value is set to 3 somehow. But when using statement: p h.default the result is 'nil'. However, if trying to print a non-existing value, such as 'key1' it prints 3. p h['key1' #prints 3 So it behaves as default value is set to 3
17th May 2018, 10:23 AM
Adam Aksu
Adam Aksu - avatar
+ 2
"The truth is out there" (c)
17th May 2018, 10:52 AM
Nikita Semenov
Nikita Semenov - avatar
+ 2
Thanks [user id="3613244"]Nikita Semenov www.taskker.club[/user] . I just tried this def 1 2 3 end p h # prints 3 So the block in the hash in my question is returning 3 the last thing it does and therefore default value is set to 3? Don't understand though why p h.default doesn't print 3.. But that is maybe explained in the link you provided.. will read that.
17th May 2018, 10:58 AM
Adam Aksu
Adam Aksu - avatar
+ 2
h1 = Hash.new(7) h1.default #=> 7 h1.default_proc #=> nil h1[123] #=> 7 h2 = Hash.new{7} h2.default #=> nil h2.default_proc.call #=> 7 h2[123] #=> 7 Hope this will help you to understand
17th May 2018, 11:14 AM
Nikita Semenov
Nikita Semenov - avatar
+ 2
I guess when you call h[123] ruby return h.default. If result is nil, then it search for h.default_proc and return h.default_proc.call
17th May 2018, 11:19 AM
Nikita Semenov
Nikita Semenov - avatar