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 --
GPG-PGP Public Key: 0xE4E8FAB1
Fingerprint: 14D3 A373 E926 7737 DF32 502B A4C4 1CE2 E4E8 FAB1
***********************************************
"“Machines take me by surprise with great frequency.” A. Turing

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:

···

--
Posted via http://www.ruby-forum.com/.

Hi --

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

···

On Thu, 23 Jul 2009, Mirko Viviani wrote:

--
David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.rubypal.com
Now available: The Well-Grounded Rubyist (http://manning.com/black2)
Training! Intro to Ruby, with Black & Kastner, September 14-17
(More info: http://rubyurl.com/vmzN)

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 Williams <toastkid.williams@gmail.com>

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:
--
Posted via http://www.ruby-forum.com/.

--
-- Mirko Viviani --
GPG-PGP Public Key: 0xE4E8FAB1
Fingerprint: 14D3 A373 E926 7737 DF32 502B A4C4 1CE2 E4E8 FAB1
***********************************************
"“Machines take me by surprise with great frequency.” A. Turing

Mirko Viviani schrieb:

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

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

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:
--
Posted via http://www.ruby-forum.com/.

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

···

2009/7/23 Max Williams <toastkid.williams@gmail.com>

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

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]

···

2009/7/23 Max Williams <toastkid.williams@gmail.com>

--
Posted via http://www.ruby-forum.com/.

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

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

···

2009/7/23 Max Williams <toastkid.williams@gmail.com>

--
Posted via http://www.ruby-forum.com/.

thank's to all.... this is a think I would remember :smiley:

···

2009/7/23 7stud -- <bbxx789_05ss@yahoo.com>

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 Williams <toastkid.williams@gmail.com>

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
--
Posted via http://www.ruby-forum.com/.

--
-- Mirko Viviani --
GPG-PGP Public Key: 0xE4E8FAB1
Fingerprint: 14D3 A373 E926 7737 DF32 502B A4C4 1CE2 E4E8 FAB1
***********************************************
"“Machines take me by surprise with great frequency.” A. Turing

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

···

--
Posted via http://www.ruby-forum.com/.

Hi --

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

···

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

--
David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.rubypal.com
Now available: The Well-Grounded Rubyist (http://manning.com/black2)
Training! Intro to Ruby, with Black & Kastner, September 14-17
(More info: http://rubyurl.com/vmzN)

Max Williams 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.)
--
Posted via http://www.ruby-forum.com/.

ah, cool, thanks.

···

--
Posted via http://www.ruby-forum.com/.