Given
a = [[:a, :b, :c]]
1) I understand this
a.each{|(x, y), z| p z} # => :b
that there are two variables (x, y) and z, so the third element :c is thrown away, and z matches :b. And I understand this
a.each{|(x, y), z| p y} # => nil
that (x, y) matches :a, and since it is not an array, there are no elements to it, and so y matches nil.
But how does
a.each{|(x, y), z| p x} # => :a
work? I expect nil to be returned.
2) Why are the return values like this?
a.each{|(x, y)| p x} #=> :a
a.each{|(x, y)| p y} #=> :b
I expect them to both return nil.
It’s because of the syntax of parallel assignment.
So
a.eachhas only one element to iterate, which is[:a, :b, :c].In the first case:
Here
(x, y)is an array to match the first element:a, andxgets it, thenzsimply matches the second element:b.And in the second case:
Here
(x, y)as an entire array matches the array[:a, :b, :c], soxandyget:aand:brespectively.This is just like requiring the “args + optional args (keyword args) + rest args” combination match provided arguments. It is just smart enough to take arguments by sequence.
Another smart example:
In either case above, it will simply make the best guess on what it should take.