Unpacking an array with the star operator

Hello Group,

I just noticed the following behaviour:

$ irb --prompt-mode xmp
*[:x]
SyntaxError: compile error
(irb):1: syntax error
        from (irb):1
a=*[:x]
    ==>:x

and wondered why it is the case. I always understood the * operator as pack/unpack array operator. So I would have expected the following behaviour.

*[:x] => :x

What is the reason for * being implemented as it is?

After reading this again I see, that it may be the problem with

*[:x, :y] => ???

So in fact maybe I should not wonder. So let me rephrase it into "what exactly does the * return", because I thought "every ruby expressions retruns something" and a = *[:x] are two expressions.

And is the * a private kernel method or where is it defined?

Regards,

Brian

PS: Sorry if this is a dumb question.

···

--
Brian Schröder
http://www.brian-schroeder.de/

"Brian Schröder" <ruby@brian-schroeder.de> schrieb im Newsbeitrag
news:20041130174018.40e55108@black.wg...

Hello Group,

I just noticed the following behaviour:

$ irb --prompt-mode xmp
*[:x]
SyntaxError: compile error
(irb):1: syntax error
        from (irb):1
a=*[:x]
    ==>:x

and wondered why it is the case. I always understood the * operator as

pack/unpack array operator. So I would have expected the following
behaviour.

*[:x] => :x

No, it does not pack / unpack an array. You can only use it in a
situation where there is an assignment. The star indicates, that a given
value should be enumerated and assigned to lvalues in order (this applies
also to method argument lists).

What is the reason for * being implemented as it is?

After reading this again I see, that it may be the problem with

*[:x, :y] => ???

No, it doesn't matter how many elements you put into the array.

So in fact maybe I should not wonder. So let me rephrase it into "what

exactly does the * return", because I thought "every ruby expressions
retruns something" and a = *[:x] are two expressions.

It's not exactly an expression that returns something. It's more like a
compiler directive - if you look for an analogy.

And is the * a private kernel method or where is it defined?

I'd guess that it's implemented somewhere in the Ruby interpreter - not in
any particular class or module - as it is *not* an operator in the usual
meaning of the word.

PS: Sorry if this is a dumb question.

I don't think it's a dumb question.

Kind regards

    robert

PS: Some examples:

17:46:05 [robert.klemme]: irbs

class Foo
include Enumerable
def each() yield "foo" end
end

=> nil

Foo.new.to_a

=> ["foo"]

a,b=*Foo.new

=> ["foo"]

a

=> "foo"

b

=> nil

a,b=Foo.new

=> [#<Foo:0x1017a958>]

a

=> #<Foo:0x1017a958>

b

=> nil

Hi --

"Brian Schröder" <ruby@brian-schroeder.de> schrieb im Newsbeitrag
news:20041130174018.40e55108@black.wg...
> Hello Group,
>
> I just noticed the following behaviour:
>
> $ irb --prompt-mode xmp
> *[:x]
> SyntaxError: compile error
> (irb):1: syntax error
> from (irb):1
> a=*[:x]
> ==>:x
>
> and wondered why it is the case. I always understood the * operator as
pack/unpack array operator. So I would have expected the following
behaviour.
>
> *[:x] => :x

No, it does not pack / unpack an array. You can only use it in a
situation where there is an assignment. The star indicates, that a given
value should be enumerated and assigned to lvalues in order (this applies
also to method argument lists).

It doesn't have to be an assignment; you can do:

  irb(main):003:0> [1,2,*[3,4]]
  => [1, 2, 3, 4]

or:

  irb(main):004:0> arr = [1,2,3,4]
  => [1, 2, 3, 4]
  irb(main):005:0> Hash[*arr]
  => {1=>2, 3=>4}

I like to think of it as the unarr?ay (unary/unarray) operator :slight_smile:

David

···

On Wed, 1 Dec 2004, Robert Klemme wrote:

--
David A. Black
dblack@wobblini.net

Thanks for the answers. I again learned something new. I didn't knew that each enumerable could be "unstarred".

Regards,

Brian

···

On Wed, 1 Dec 2004 01:52:48 +0900 "Robert Klemme" <bob.news@gmx.net> wrote:

17:46:05 [robert.klemme]: irbs
>> class Foo
>> include Enumerable
>> def each() yield "foo" end
>> end
=> nil
>> Foo.new.to_a
=> ["foo"]
>> a,b=*Foo.new
=> ["foo"]
>> a
=> "foo"
>> b
=> nil
>> a,b=Foo.new
=> [#<Foo:0x1017a958>]
>> a
=> #<Foo:0x1017a958>
>> b
=> nil

--
Brian Schröder
http://www.brian-schroeder.de/

David A. Black wrote:

"Brian Schröder" <ruby@brian-schroeder.de> schrieb

*[:x] => :x

No, it does not pack / unpack an array. You can only use it in a
situation where there is an assignment. The star indicates, that a given
value should be enumerated and assigned to lvalues in order (this applies
also to method argument lists).

It doesn't have to be an assignment; you can do:

  irb(main):003:0> [1,2,*[3,4]]
  => [1, 2, 3, 4]

I think this is just another case of a hidden method call. I like to think of [1, 2, 3] as Array[1, 2, 3] which is Array.(1, 2, 3)

So maybe that sample could be thought of as Array.(1, 2, *Array.(3, 4)) -- isn't Ruby an oddly lovable language? :slight_smile:

or:

  irb(main):004:0> arr = [1,2,3,4]
  => [1, 2, 3, 4]
  irb(main):005:0> Hash[*arr]
  => {1=>2, 3=>4}

I like to think of it as the unarr?ay (unary/unarray) operator :slight_smile:

Same here, equivalent to Hash.(1, 2, 3, 4). So I guess the theory of the original poster (* interpolates an Array into an assignment list) still holds true.

···

On Wed, 1 Dec 2004, Robert Klemme wrote:

"David A. Black" <dblack@wobblini.net> schrieb im Newsbeitrag
news:Pine.LNX.4.44.0411301028320.4191-100000@wobblini...

Hi --

>
> "Brian Schröder" <ruby@brian-schroeder.de> schrieb im Newsbeitrag
> news:20041130174018.40e55108@black.wg...
> > Hello Group,
> >
> > I just noticed the following behaviour:
> >
> > $ irb --prompt-mode xmp
> > *[:x]
> > SyntaxError: compile error
> > (irb):1: syntax error
> > from (irb):1
> > a=*[:x]
> > ==>:x
> >
> > and wondered why it is the case. I always understood the * operator

as

> pack/unpack array operator. So I would have expected the following
> behaviour.
> >
> > *[:x] => :x
>
> No, it does not pack / unpack an array. You can only use it in a
> situation where there is an assignment. The star indicates, that a

given

> value should be enumerated and assigned to lvalues in order (this

applies

> also to method argument lists).

It doesn't have to be an assignment; you can do:

  irb(main):003:0> [1,2,*[3,4]]
  => [1, 2, 3, 4]

Thanks David! I didn't think of this case. I wonder whether this can be
viewed as an anonymous assignment.

or:

  irb(main):004:0> arr = [1,2,3,4]
  => [1, 2, 3, 4]
  irb(main):005:0> Hash[*arr]
  => {1=>2, 3=>4}

That's a method argument list.

I like to think of it as the unarr?ay (unary/unarray) operator :slight_smile:

IMHO it's not an operator, as it has mainly compile time effects, i.e., it
controls which values are assigned to which variables (in an assignment).

Note also, that the star can appear on the left side of an assignment, too
(or in the argument list of a method definition, which is basically the
same):

a,b,c = %w{aaa bbb ccc ddd}

=> ["aaa", "bbb", "ccc", "ddd"]

a

=> "aaa"

b

=> "bbb"

c

=> "ccc"

a,b,*c = %w{aaa bbb ccc ddd}

=> ["aaa", "bbb", "ccc", "ddd"]

a

=> "aaa"

b

=> "bbb"

c

=> ["ccc", "ddd"]

Kind regards

    robert

···

On Wed, 1 Dec 2004, Robert Klemme wrote: