The Wayback Machine - https://web.archive.org/web/20220708131954/https://gist.github.com/stevenharman/5664318
Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A subtle difference between Ruby's Hash.fetch(:key, :default) vs. (Hash[:key] || :default)
h = {
'a' => :a_value,
'b' => nil,
'c' => false
}
h.fetch('a', :default_value) #=> :a_value
h.fetch('b', :default_value) #=> nil
h.fetch('c', :default_value) #=> false
h.fetch('d', :default_value) #=> :default_value
(h['a'] || :default_value) #=> :a_value
(h['b'] || :default_value) #=> :default_value
(h['c'] || :default_value) #=> :default_value
(h['d'] || :default_value) #=> :default_value
@redex2000
Copy link

redex2000 commented May 14, 2016

Good example

@salsysd
Copy link

salsysd commented Apr 11, 2017

#themoreyouknow


Is this difference only with MRI, what about JRuby, etc.? This company I'm working with deploys their ruby apps in production on Jruby, but we all develop locally on MRI, bitten me in the ass a few times. So just curious if you've discovered this difference between rubies/interpreter?

@marvin-min
Copy link

marvin-min commented May 15, 2017

👍

@saraid
Copy link

saraid commented Aug 1, 2017

For anyone who doesn't know, this is because Hash#fetch is interchangeable with hash.key?(key) ? hash[key] : default. I.e., #fetch checks for key existence, whereas || is testing for value falsiness. That's an extremely large distinction.

Note that {}[non_existent_key] still returns nil, but {}.fetch(non_existent_key) raises a KeyError.

@garrett-olson
Copy link

garrett-olson commented Aug 21, 2017

Good info.

@arvindvyas
Copy link

arvindvyas commented Aug 12, 2018

💯

@theasteve
Copy link

theasteve commented Jan 17, 2019

Why use fetch if default value is not returned and nil can blow the application up? I'm now confused

@stevenharman
Copy link
Author

stevenharman commented Jun 28, 2019

Why use fetch if default value is not returned and nil can blow the application up? I'm now confused

fetch does return a default value, presuming you provide one. You can also provide a block, the return value of which, will be used as the "default value" in the case the key is missing from the hash.

@gat-bryszard
Copy link

gat-bryszard commented Mar 24, 2021

You can get exactly same result if you do Hash.fetch(:key, ::default_value) || :default_value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment