From: Benoit Daloze Date: 2009-12-21T20:51:39+09:00 Subject: [ruby-core:27267] Re: [Bug #2422] splat operator fails on array of 1 element --0023541873d834b009047b3b9d67 Content-Type: text/plain; charset=ISO-8859-1 2009/12/21 katz bo > Issue #2422 has been updated by katz bo. > > > Dave B wrote: > >Producing an empty array from a splatted empty array seems unproductive. > Agreed. > > Tanaka Akira wrote: > > 2009/12/21 katz bo : > >> I personally think *[1, 2, 3] should be always unpacked first. > > > > Your way cannot interpret a = *[]. > > > > a = *[] > > a = > > > > It is not a valid Ruby statement. > > Why not think of this as a special case? > There's always something special about zeros and nils in my shallow > opinion. :P > > In fact, a = *[] should _exactly_ be a = IMHO. And strictly speaking, a = > *[] should not be a valid syntax at all. > But, this is Ruby! > > What does Ruby do with a = *[] ? Let me illustrate an IMO proper way: > Ruby looks at *[] and goes, "Fine, let me unpack it." > Ruby unpacks *[]. > Then Ruby goes, "Nothing? But I can't _carry_ ! No.. not in an > assignment! Wait.. Let's do it!" > Ruby marks it as nil. > > One of the reasons why I think this special case should be handled this > way, is the way Ruby handles parallel assignments: > a, b = [1] # => [1] > p a # => 1 > p b # => nil > This is not the case, for example, in python. (It spits "ValueError: need > more than 1 value to unpack" when you do a, b = [1]). > Since Ruby auto-pads the out-of-range elements as nil, we have a good > reason to make Ruby automatically handle a = *[] in this way. > > I also have a vague observation that the splatted array is actually dealt > differently by the internal Ruby in some cases. Assignment is such a case. > > # COMMAND # OUTPUT # RETURN # NOTES > p # # => nil > p *[] # # => nil # Fits very well in my "unpack first" theory > p nil # nil # => nil > a = *[]; p a # [] # => [] # ruby 1.9; should both be nil IMO > a =* []; p a # [] # => [] # ruby 1.9; should both be nil IMO; the > space between * and [ is allowed! > > Additionally, I find `return' fails my expectations in a similar way > assignment does: > > def foo; return *[]; end; foo # => [] # ruby 1.9; I have doubt: nil > or []? > def bar; return *[1]; end; bar # => [1] # ruby 1.9; I was expecting 1 > def baz; return *[],*[1]; end; baz # => [1] > def ban; return *[1],*[2]; end; ban # => [1, 2] > def boo; return *[1,2]; end; boo # => [1, 2] > > We know that return packs multiple parameters into an array. This, combined > with my "unpack first" theory, makes me think the first two results are not > correct. But I don't know. Can't test it with ruby 1.8 since I don't have it > installed. > > Can somebody post the result to the code above for ruby 1.8? > > Here it is: COMMAND # 1.9 vs 1.8 p # => nil p *[] # => nil p nil # => nil a = *[]; p a # => [] vs nil a =* []; p a # => [] vs nil These 2 last look very weird. --------- def foo; return *[]; end; foo # => [] vs nil def bar; return *[1]; end; bar # => [1] vs 1 def baz; return *[],*[1]; end; baz # => [1] vs SyntaxError: compile error ( (irb):4: syntax error, unexpected tSTAR, expecting tAMPER def baz; return *[],*[1]; end; baz ^ (irb):4: syntax error, unexpected ';', expecting tCOLON2 or '[' or '.' def baz; return *[],*[1]; end; baz ^ ) def ban; return *[1],*[2]; end; ban # => [1, 2] vs SyntaxError: compile error ( (irb):4: syntax error, unexpected tSTAR, expecting tAMPER def ban; return *[1],*[2]; end; ban # => [1, 2] ^ (irb):4: syntax error, unexpected ';', expecting tCOLON2 or '[' or '.' def ban; return *[1],*[2]; end; ban # => [1, 2] ^ ) def boo; return *[1,2]; end; boo # => [1, 2] vs [1, 2] So here we clearly see how 1.9 is more 'safe' ... --0023541873d834b009047b3b9d67 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable

2009/12/21 katz bo <= ;redmine@ruby-lang.org>
Issue #2422 has been updated by katz bo.


Dave B wrote:
>Producing an empty array from a splatted empty array seems unproductive= .
Agreed.

Tanaka Akira wrote:
> 2009/12/21 katz bo <redmin= e@ruby-lang.org>:
>> I personally think *[1, 2, 3] should be always unpacked first.
>
> Your way cannot interpret a =3D *[].
>
> a =3D *[]
> a =3D
>
> It is not a valid Ruby statement.

Why not think of this as a special case?
There's always something special about zeros and nils in my shallow opi= nion. :P

In fact, a =3D *[] should _exactly_ be a =3D IMHO. And strictly speaking, a= =3D *[] should not be a valid syntax at all.
But, this is Ruby!

What does Ruby do with a =3D *[] ? Let me illustrate an IMO proper way:
Ruby looks at *[] and goes, "Fine, let me unpack it."
Ruby unpacks *[].
Then Ruby goes, "Nothing? But I can't _carry_ <nothing>! No.= . not in an assignment! Wait.. Let's do it!"
Ruby marks it as nil.

One of the reasons why I think this special case should be handled this way= , is the way Ruby handles parallel assignments:
a, b =3D [1] # =3D> [1]
p a # =3D> 1
p b # =3D> nil
This is not the case, for example, in python. (It spits "ValueError: n= eed more than 1 value to unpack" when you do a, b =3D [1]).
Since Ruby auto-pads the out-of-range elements as nil, we have a good reaso= n to make Ruby automatically handle a =3D *[] in this way.

I also have a vague observation that the splatted array is actually dealt d= ifferently by the internal Ruby in some cases. Assignment is such a case.
# COMMAND =A0 =A0# OUTPUT # RETURN # NOTES
p =A0 =A0 =A0 =A0 =A0 =A0# =A0 =A0 =A0 =A0# =3D> nil
p *[] =A0 =A0 =A0 =A0# =A0 =A0 =A0 =A0# =3D> nil # Fits very well in my = "unpack first" theory
p nil =A0 =A0 =A0 =A0# nil =A0 =A0# =3D> nil
a =3D *[]; p a # [] =A0 =A0 # =3D> [] =A0# ruby 1.9; should both be nil = IMO
a =3D* []; p a # [] =A0 =A0 # =3D> [] =A0# ruby 1.9; should both be nil = IMO; the space between * and [ is allowed!

Additionally, I find `return' fails my expectations in a similar way as= signment does:

def foo; return *[]; end; =A0 =A0 =A0 foo # =3D> [] =A0# ruby 1.9; I hav= e doubt: nil or []?
def bar; return *[1]; end; =A0 =A0 =A0bar # =3D> [1] # ruby 1.9; I was e= xpecting 1
def baz; return *[],*[1]; end; =A0baz # =3D> [1]
def ban; return *[1],*[2]; end; ban # =3D> [1, 2]
def boo; return *[1,2]; end; =A0 =A0boo # =3D> [1, 2]

We know that return packs multiple parameters into an array. This, combined= with my "unpack first" theory, makes me think the first two resu= lts are not correct. But I don't know. Can't test it with ruby 1.8 = since I don't have it installed.

Can somebody post the result to the code above for ruby 1.8?


Here it is:
COMMAND # 1.= 9 vs 1.8

p =A0 =A0 =A0 =A0 =A0 =A0 =A0=A0 # =3D> nil
p *[] =A0 =A0 =A0=A0=A0 =A0=A0 # =3D> nil
p nil =A0 =A0 =A0=A0=A0 =A0=A0 # =3D> nil
a =3D *[]; p a # =3D> [] vs nil
a =3D* []; p a # =3D> []=A0 vs nil

These 2 last look very weird.<= br>
---------

= def foo; return *[= ]; end; foo # =3D> [] vs nil
def bar; return *[= 1]; end; bar # =3D> [1] vs 1

def baz; return *[],= *[1]; end;=A0 baz # =3D> [1] vs SyntaxError: compile error
(=A0=A0
=A0=A0=A0 (= irb):4: syntax error, unexpected tSTAR, expecting tAMPER

=A0=A0=A0 def baz; return *[],*[1]; end;=A0 baz
=A0 =A0 =A0 =A0 =A0 =A0= =A0 =A0 =A0=A0=A0=A0=A0=A0=A0=A0 ^
=A0=A0= =A0 (irb):4: syntax error, unexpected ';', expecting tCOLON2 or = 9;[' or '.'
=A0=A0=A0 def baz; retu= rn *[],*[1]; end;=A0 baz
=A0=A0=A0 =A0 =A0= =A0 =A0 =A0 =A0 =A0 =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 ^
)

def ban;= return *[1],*[2]; end; ban # =3D> [1, 2] vs SyntaxError: compile error<= /span>
(
=A0=A0 (irb):4: syntax error, unexpected tSTAR, expecting tAMPE= R
=A0=A0 def ban; return = *[1],*[2]; end; ban # =3D> [1, 2]
=A0 = =A0 =A0 =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 ^
=A0=A0 (irb):4: syntax = error, unexpected ';', expecting tCOLON2 or '[' or '.&#= 39;
=A0=A0 def ban; return *[1],*[2]; end;= ban # =3D> [1, 2]
=A0 =A0 =A0 =A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 ^
)


def boo; return *[1,2]; end; boo # =3D> [1, 2] vs [1, 2]
So here we clearly see how 1.9 is more 'safe' ...

<= /span>
--0023541873d834b009047b3b9d67--