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.
a = [[:a, :b, :c]]
So a.each
has only one element to iterate, which is [:a, :b, :c]
.
In the first case:
(x, y), z = [:a, :b, :c]
#=> x == :a, y == nil, z == :b
Here (x, y)
is an array to match the first element :a
, and x
gets it, then z
simply matches the second element :b
.
And in the second case:
(x, y) = [:a, :b, :c]
#=> x == :a, y == :b
Here (x, y)
as an entire array matches the array [:a, :b, :c]
, so x
and y
get :a
and :b
respectively.
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:
(a,b) = 1,2
=> [1, 2] # array match
#=> a == 1, b == 2
(a,b)=[1,2]
=> [1, 2] # array match
#=> a == 1, b == 2
In either case above, it will simply make the best guess on what it should take.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With