When you use the block syntax with Hash.new to define a default value, you lock yourself to only using the square bracket syntax for value lookup. The fetch method ignores the block, default, and default_proc.

This bit me hard this week, and my pair, @gd, got to watch me flounder on why fetch wasn’t getting the default value.

By the way, the Hash.new with a block is great for memoization of calculated or network lookup data.

#Ruby #RubyTips #RubyGotchas #ThisWeekILearned #TWIL

If you wish to memoize (cache / calculate only once) a value, a Hash with a block in ruby is a good way to do it.

For example:

h = Hash.new do |hash, key|
hash[key] = "Default value for #{key} "
end

h.fetch(:no_such, "not defined")
#=> "not defined"

h[:no_such]
# => "Default value for no_such"

This is means the value for h[:no_such] gets set the first time it is accessed and no longer needs to be calculated with the block, but fetch does not use that default proc.

#Ruby #RubyTips

Note, you don't need to store the default value in the proc, only if you wish to no longer calculate it on next access.

If you don't store it, it will be called every time until the key is set on the hash.

@jnanney it bothers me that the arity for the default_proc and the fetch block is different.
After reading this I wanted to see if the default_proc could be used:

h = Hash.new do |hash, key|
hash[key] = "Default value for #{key}"
end
puts h.fetch(:nope, &h.default_proc.curry(2)[h])

It works... but I would only use it if it was buried in some object that wraps the hash or something.

@saturnflyer It makes sense as to why fetch doesn't call the default when you really think about it, Fetch is used to throw an error if a key doesn't exist, or use a default if supplied to the fetch method. It just was surprising behavior to me without having thought hard on it until it bit me.
@jnanney yeah. I agree. after playing with it. but going in you think "[] is the same as fetch but you can supply an alternative". turns out that's not _really_ true
@jnanney @gd TIL! This seems to violate the principle of least surprise and therefore should be fixed in the language itself, no?

@elight @gd If you really think about it, fetch is used to throw an exception when a key doesn't exist, so it probably shouldn't use the default_proc.

I just need to remember that :[] is not the same as :fetch, both have different use cases.

@jnanney @gd Good point. I'm admittedly rusty!