Ruby "star".... what's it?

Hi everybody.
What means this snippet of code? Why use the “star” ?

myarray = [1,2,3,4,5,6,6]
qa = *myarray

Thank you.

Mirko Viviani wrote:

Hi everybody.
What means this snippet of code? Why use the “star” ?

myarray = [1,2,3,4,5,6,6]
qa = *myarray

Thank you.

In this example it doesn’t really do anything, i think. Normally you
would use the * in an argument list, in a method definition, to
effectively say ‘pull all arguments after this into a single array’, eg

def foo(mainarg, *otherargs)
puts mainarg.inspect
puts otherargs.inspect
end
=> nil

foo(1,2,3,4,5,6)
1
[2, 3, 4, 5, 6]
=> nil

In this sense it’s like * in a regular expression, meaning ‘any number
of arguments’. That’s how i understand it anyway, a more precise
description will probably be forthcoming :slight_smile:

Sorry,
Complete code was like this
x, *xs = *myarray

after executing, x is 1 and xs [2,3,4,5,6,6] … :o

2009/7/23 Max W. [email protected]

Mirko Viviani schrieb:

effectively say ‘pull all arguments after this into a single array’, eg

irb(main):001:0> x = 0
=> 0
irb(main):002:0> xs = [0, 0]
=> [0, 0]
irb(main):003:0> myarray = [1, 2, 3]
=> [1, 2, 3]
irb(main):004:0> x, *xs = *myarray
=> [1, 2, 3]
irb(main):005:0> x
=> 1
irb(main):006:0> xs
=> [2, 3]
irb(main):007:0> x = 0
=> 0
irb(main):008:0> xs = [0, 0]
=> [0, 0]
irb(main):009:0> x, xs = myarray
=> [1, 2, 3]
irb(main):010:0> x
=> 1
irb(main):011:0> xs
=> 2

The * is also called the “splat operator”. It is used to split up an
array in is parts or
the other way round (like in the method definition already posted). You
could also
do things like:

def foo(x, y)
puts x
puts y
end

ary = [1, 2]
foo(ary) #=> ArgumentError
foo(*ary) #=> 1, 2

Marvin

Mirko Viviani wrote:

Sorry,
Complete code was like this
x, *xs = *myarray

after executing, x is 1 and xs [2,3,4,5,6,6] … :o

2009/7/23 Max W. [email protected]

Ah, well there you go. In ruby, you can assign multiple variables to
multiple values simultaneously: effectively on the left side of the =
you have a list of variables and on the right you have a list of values.
If the sizes of the lists don’t match up then any extra values are
thrown away and any extra variables are set to nil. eg

However, if you use the * on the rightmost variable, then any extra
values get pulled into an array and that variable points to that array:

a, b, c = 1, 2, 3
=> [1, 2, 3]
puts a.inspect; puts b.inspect; puts c.inspect
1
2
3
=> nil
a, b, c = 1, 2
=> [1, 2]
puts a.inspect; puts b.inspect; puts c.inspect
1
2
nil
=> nil
a, b = 1, 2, 3
=> [1, 2, 3]
puts a.inspect; puts b.inspect
1
2
=> nil
a, *b = 1, 2, 3
=> [1, 2, 3]
puts a.inspect; puts b.inspect
1
[2, 3]

thank’s to all… this is a think I would remember :smiley:

2009/7/23 7stud – [email protected]

Mirko Viviani wrote:

Sorry,
Complete code was like this
x, *xs = *myarray

after executing, x is 1 and xs [2,3,4,5,6,6] … :o

2009/7/23 Max W. [email protected]

x, y, z = 1, 2, 3
puts x, y, z

–output:–
1
2
3

x, y, z = *[1, 2, 3]
puts x, y, z

–output:–
1
2
3

*y = 1, 2, 3
p y

–output:–
[1, 2, 3]

x, *y = *[1, 2, 3]
puts x
p y

–output:–
1
[2, 3]

Depending on the context the * means:

a) replace an array with its individual elements
b) gather individual elements into an array

7stud – wrote:

Depending on the context the * means:

a) replace an array with its individual elements
b) gather individual elements into an array

I said a more precise explanation would be forthcoming :slight_smile:

7stud - am i right in thinking that if i do this

a, b = 1, 2

ruby is automatically starring just the right side of the expression,
under the hood? eg

a,b = 1,2
=> [1, 2]

puts a.inspect;puts b.inspect
1
2
=> nil

a,b = [1,2]
=> [1, 2]

puts a.inspect;puts b.inspect
1
2
=> nil

[a,b] = [1,2]
SyntaxError: compile error
(irb):37: syntax error, unexpected ‘=’, expecting $end
[a,b] = [1,2]
^
from (irb):37

Hi –

On Thu, 23 Jul 2009, 7stud – wrote:

Depending on the context the * means:

a) replace an array with its individual elements
b) gather individual elements into an array

It’s changed in 1.9. * on the left no longer has the same “un-array”
semantics.

a = [1]; a
=> [1]

*a = [1]; a
=> [1]

I’m kind of drawing a blank on why this change was made.

David

Max W. wrote:

7stud - am i right in thinking that if i do this

a, b = 1, 2

ruby is automatically starring just the right side of the expression,
under the hood? eg

In pickaxe2, p. 91, the rule is:

When an assignment has more than one lvalue, the assignment expression
returns an array of the rvalues. Testing that out:

result = (x, y = [1], [2, 3])
p result

So I guess you could say "ruby is automatically starring the right hand
side of a parallel assignment if there is more than one lvalue, and the
resulting array is the value of the entire expression.

And I guess this wasn’t a very good example:

x, y, z = *[1, 2, 3]
puts x, y, z

–output:–
1
2
3

Because you can eliminate the star and get the same output:

x, y, z = [1, 2, 3]
p x
p y
p z

–output:–
1
2
3

But this is where the star makes a difference:

x, y, z = 1, [2, 3]
p x
p y
p z

–output:–
1
[2, 3]
nil

x, y, z = 1, *[2, 3]
p x
p y
p z

–output:–
1
2
3

(This applies to ruby 1.8. See David Black’s post for 1.9 behavior.)

ah, cool, thanks.

Hi –

On Thu, 23 Jul 2009, Mirko Viviani wrote:

Hi everybody.
What means this snippet of code? Why use the “star” ?

myarray = [1,2,3,4,5,6,6]
qa = *myarray

In addition to the examples in the other answers, note that the star
has some new behavior in 1.9.

Here’s the 1.8 behavior.

*a = 1; a
=> [1]

*a = [1]; a
=> [[1]]

*a = [[1]]; a
=> [[[1]]]

In each case, the star indicates one “missing” level of array
wrapping. In 1.9, that’s changed:

*a = 1; a
=> [1]

*a = [1]; a
=> [1]

*a = [[1]]; a
=> [[1]]

*a = 1 and *a = [1] have the same result. (I know there was a lot of
discussion about this when it was being changed but I can’t remember
exactly what the rationale was.)

David