Why can I do this? It makes no syntactical sense!
It makes a perfect sense. It is an example of parallel assignment.
When you use = what is happening is each of the list of variables on the left of = are assigned to each of the list of expressions on the right of =.
first, second = ['uno', 'dos']
# is equivalent to
first, second = 'uno', 'dos'
If there are more variables on the left, than expressions on the right, those left variables are assigned with nil:
first, second = 'uno'
first #=> 'uno'
second #=> nil
As to
words = ['uno', 'dos']
first, second = words
first #=> 'uno'
second #=> 'dos'
It is not assigning the whole words array to first leaving second with nil, because while parallel assignment Ruby tries to decompose the right side expression, and does so if it is an instance of Array.
[TIL] Moreover, it attempts to call to_ary on the right side expression, and if it responds to the method, decomposes accordingly to that object's to_ary implementation (credits to @Stefan):
string = 'hello world'
def string.to_ary; split end
first, second = string
first #=> 'hello'
second #=> 'world'
hash.each { |k, v| ... }instead ofhash.each { |arr| ... }one, two, three, _, *rest = [*1..10]._to denote that you are not intending to use the result without triggering a warning (e.g._foo)? This is the same, just without even a name.