-
Notifications
You must be signed in to change notification settings - Fork 378
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Add benchmark for Hash#dig vs #[] vs #fetch #102
Conversation
end | ||
|
||
x.report 'Hash#[] fallback' do | ||
((((h[:a] || {})[:b] || {})[:c] || {})[:d] || {})[:e] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ouch, do people ever really do it this way? far more common I think is:
h[:a] && h[:a][:b] && ## etc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure which way is more common. Should I use one example over the other or include both?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I think, the way proposed by @nateberkopec is more effective in case when none of the keys are exists, because you don't need to create all of these hashes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added the more common style to the benchmark, see 95b8ea4
end | ||
|
||
x.report 'Hash#fetch fallback' do | ||
h.fetch(:a, {}).fetch(:b, {}).fetch(:c, {}).fetch(:d, {}).fetch(:e, nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fetch(:a, {})
creates new object EVERY time even when it's not needed.
More appropriate would be:
h.fetch(:a) { {} }.fetch(:b) { {} }...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your notation will create Procs for every #fetch. That maybe faster or not. Seems that's another test… :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ixti I'd like to keep it as is because I see the current approach more often.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mblumtritt in fact it will not. Why would it create Proc?
In any case, @dideler I tend to agree that probably some people use fetch(key, {})
.
And that looks pretty fine, but in this case it worth to "cache" that object:
o = {}
h.fetch(:a, o).fetch(:b, o)
That's just my thoughts. I don't insist on anything :D
More interesting would be to compare H = { :a => { :b => { :d => true } } }
H.dig(:a, :b, :c, :d) # => nil
H[:a] && H[:a][:b] && H[:a][:b][:c] && H[:a][:b][:c][:d] # => nil |
I find the safe path most interesting because you can compare more options, but here are all cases. Safe:
Broken at last key:
Broken at intermediate key:
|
@dideler I'm absolutely agree that |
73b2c8d
to
437d8f8
Compare
👍, how's 437d8f8? |
LGTM! 👍 |
Thanks @JuanitoFatas - I would love to be a collaborator! |
Yay! ❤️ |
Comparison of how Ruby 2.3.0's
Hash#dig
performs to similar methods.Unsafe retrieval options are included. I can remove them if you consider them noisy.