Why does parallel assignment of a single empty array assign multiple nils?

528 Views Asked by At

I want to assign an empty array to multiple variables. Here is what I'm doing:

irb(main):015:0> a, b, c = []
=> []
irb(main):016:0> a
=> nil
irb(main):017:0> b
=> nil
irb(main):018:0> c
=> nil

It gives me nil. I wonder why? But if I did this:

irb(main):019:0> a, b, c = [], [], []
=> [[], [], []]
irb(main):020:0> a
=> []
irb(main):021:0> b
=> []
irb(main):022:0> c
=> []

then it works as I expect, but it's a little bit longer than the first one. What's wrong with the first example?

4

There are 4 best solutions below

0
ZelluX On BEST ANSWER

I believe this example will help you understand the problem:

[1] pry(main)> a, b, c = [1,2]
=> [1, 2]
[2] pry(main)> a
=> 1
[3] pry(main)> b
=> 2
[4] pry(main)> c
=> nil

Now back to your problem, you are trying to assign the elements in an empty array to variables, as a result, the three variables all get nil value.

0
zed_0xff On
a = b = c = []

but note that all variables will be assigned the same array
so:

a = b = []
b << 1
p b        # [1]
p a        # [1]
3
Todd A. Jacobs On

Parallel Assignment With Single Rvalue

If the assignment contains multiple lvalues and one rvalue, the Ruby attempts to expand the rvalue into an array as if you'd called #to_a on the rvalue. So, the problem with your example of a, b, c = [] is that it is semantically equivalent to:

a, b, c = nil.to_a

which would obviously assign nil to the first variable, and leave the others unassigned (which is also nil). In contrast, consider this:

a, b, c = 1
a
# => 1
b
# => nil
c
# => nil

The same principle is at work, but now you can see that the first lvalue does receive an assignment from the right-hand side; it just wasn't obvious when the assignment was nil.

0
Andrew Haines On

Ruby destructures arrays when you do parallel assignment:

a, b, c = [:foo, :bar, :baz]
a # => :foo
b # => :bar
c # => :baz

If you give it an array with too few entries, it sets the remaining values to nil:

a, b, c = [:foo, :bar]
a # => :foo
b # => :bar
c # => nil

So your first example is just the natural extension of this - an empty array definitely has too few entries to assign any of the variables!