Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why does ruby parallel assignment with array of strings returns string

Tags:

ruby

I'm not sure what exactly is going on with the code snippet below.

>> a, b = ["ho", "hey"]
=> ["ho", "hey"]
>> a
=> "ho"
>> b
=> "hey"    
>> c, d = "foo", "bar"
=> ["foo", "bar"]
>> c 
=> "foo"
>> d
=> "bar"
>> a, b = ["blerg"], ["baz"]
=> [["blerg"], ["baz"]]
>> a
=> ["blerg"]
>> b 
=> ["baz"]

Why wouldn't line 1 return a => ["ho"]?

So behind the scenes, what's the difference between these three assignments (a, b = ["ho", "hey"], c, d = "foo", "bar", a, b = ["blerg"], ["baz"])?

like image 595
CHK Avatar asked Feb 16 '13 18:02

CHK


People also ask

How do you assign a value to an array in Ruby?

To update an element in the array, assign a new value to the element's index by using the assignment operator, just like you would with a regular variable.

How do you access an array of objects in Ruby?

In Ruby, there are several ways to retrieve the elements from the array. Ruby arrays provide a lot of different methods to access the array element. But the most used way is to use the index of an array.

How do I read an array element in Ruby?

We can use range operator with the slice method. In the first line we read elements from index 2 to 6, in the second line elements from 2 to 5. The slice method returns portions of the array, one or more elements of the array. It is possible to select a random value from an array.

Can a function return two values Ruby?

Technically Ruby doesn't return two values. It can return one array which in turn gets assigned to two variables.


2 Answers

a, b = ["ho", "hey"] 

a is assigned the first element of the array, which is the string "ho". Nothing weird.

a, b = ["blerg"], ["baz"]

a, b = [["blerg"], ["baz"]]

These two are the same, as you can see by their return values. So a is assigned the first element, which is an array with one element: ["blerg"].

Similarly,

c, d = "foo", "bar"

Is the same as

c, d = ["foo", "bar"]
like image 54
Linus Avatar answered Sep 21 '22 21:09

Linus


In Ruby, = takes a list of variables on the left, and a list of expressions on the right. It assigns the the first variable to the value of the first expression, the second variable the value of the second expression, and so on. If there are more variables than expressions, the leftover variables get assigned the value nil.

> a, b, c, d = "foo", 2+3, Array.new(2, 3), [:c, :d]
> a     # => "foo"
> b     # => 5
> c     # => [3, 3]
> d     # => [:c, :d]
> e     # => nil

There are two exceptions:

Left side has only one variable, right side has multiple expressions

In this case, the above rule would say that the variable just gets set to the value of the first expression on the right. Instead, the variable gets set to the Array consisting of the values of the expression on the right. In the example below, we see a gets the value [:b, :c], instead of just :b:

> a = :b, :c
> a    # => [:b, :c]

This is equivalent to:

> *a = :b , :c
> a    # => [:b, :c]

The other exception:

The left side has multiple variables, the right side has only one expression and it's an Array

Again, the original rule would imply that the first variable gets set to that whole Array, and the rest of the variables would be nil. However, that Array effectively ends up getting replaced with the list of its elements, and then = reverts to the "default" behaviour described in the beginning:

> a, b, c = [:d, [:e, :f]]
> a    # => :d
> b    # => [:e, :f]
> c    # => nil

This is equivalent to a, b, c = *[:d, [:e, :f]], or just a, b, c = :d, [:e, :f]

like image 27
Amit Kumar Gupta Avatar answered Sep 20 '22 21:09

Amit Kumar Gupta