One tutorial has this block of code:
h1 = ["a" => 111, "b" => 222]
h2 = ["b" => 333, "c" => 444]
h1.merge(h2) {|key, old, new| new}
# => ["a" => 111, "b" => 333, "c" => 444]
h1.merge(h2) {|key, old, new| old}
# => ["a" => 111, "b" => 222, "c" => 444]
We have a conflict with the merge. Two duplicate keys across our two arrays. new is capturing h2‘s value for "b", and outputting it forces it to take priority in the merge. Similarly, old is capturing h1‘s value for "b", and forces it to take priority.
Why are we seemingly only grabbing the values for "b"? Shouldn’t the variables be grabbing the whole array(s)? Are the block variables context-sensitive and change function when used with .merge as opposed to, say, .times? Or is it that they change function when we’re dealing with arrays instead of simple numericals? Or is it that they see a merge conflict and are like “we got to capture the point of conflict”? I thought that maybe trying to see what was in key would help,
h1.merge(h2) {|key, old, new| key}
# => ["a" => 111, "b" => "b", "c" => 444]
but it actually just made me more confused. Why is one variable capturing the key, whereas the others are capturing the two different values?
It’s merging: in
h1.merge(h2), ‘h1’ is the “old” hash, and ‘h2’ is the “new” one. The block is called only for keys that have values in both hashes. The block gets 3 arguments: each key and the corresponding values from each hash. The logic in the block chooses which one to put in the output hash for that key. Any key that is only in one hash goes straight into the output without being processed through the block.You might better understand what’s going on by running
From the Ruby-Doc.org description:
So to answer one of your specific questions, yes, the block is called conditionally, only for conflicting keys, unlike methods like .each or .delete_if, which are called for each key.