apdm apdm - 1 year ago 55
Ruby Question

Calling `Hash#map` with one vs. two block arguments


is a Hash:

entries = { foo: 1, bar: 2 }

This is the syntax I'm familiar with:

entries.map { |key, val| "#{key} #{val}" }
#=> ["foo 1", "bar 2"]

This is the syntax I came upon in a tutorial:

entries.map { |key_val| "#{key_val.first} #{key_val.last}" }
#=> ["foo 1", "bar 2"]

I'm new to Ruby, so I'm surprised that both syntaxes even work. My question are:

  1. Is there any difference between the two?

  2. Why does this work - Is it because the hash table object implements the
    interface (which provides the
    method) in two separate ways?


No, it has nothing to do with hashes and enumerables (well, almost). It is a thing I call "array destructuring". Ruby has a nice way of taking arrays apart. Suppose you have this two-element array

ary = [1, 2]

You can get its elements by accessing them individually

a = ary.first # or ary[0]
b = ary.last # or ary[-1]

Or instead you can "destructure" the array by assigning array directly to the variables

a, b = ary

a will be the first element of the array, b - the second (also the last, in this particular case).

Same thing happens in your example. Enumerable's each (which is what map calls), when used on a hash, yields arrays of two elements, a key and its value.

Now, if the block has only one parameter, it's gonna be that array. If it has two, your array will be taken apart for you.

And yes, prefer the first method. More readable.