hexsum
hexsum

Reputation: 123

Why does `$v = () = split` return 1?

perldoc says "a list assignment in scalar context returns the number of elements on the right-hand side of the list assignment" but when I try this code:

perl -e '$_="aaaaa";print $v=(()=split //)'

The output is 1 which makes me confused. (The answer I expect is 5.)

Can anybody explain this?

Upvotes: 10

Views: 679

Answers (4)

Alan Curry
Alan Curry

Reputation: 14711

split has some kind of crazy ultra-magic in it that allows it to know when it is on the right hand side of an assignment that has a list on the left hand side, and adjusts its behavior according to the number of items in that list.

This is described in perlfunc as being done "to avoid unnecessary work", but you've found an observable difference in behavior caused by that optimization.

To see some evidence of what happened, run your script through Deparse like this:

perl -MO=Deparse -e '$_="aaaaa";print $v=(()=split //)'

Update: I went looking for the code that implements this, and it's not where I expected it to be. Actually the optimization is performed by the assignment operator (op.c:Perl_newASSIGNOP) . split doesn't know that much about its context.

Upvotes: 8

Orabîg
Orabîg

Reputation: 11992

Yes, but :

perl -e '$_="aaaaa";print $v=(split //)'

gives 5, as well as

perl -e '$_="aaaaa";print $v=(@x=split //)'

Maybe your left-value () is dropping additional array elements ?

edit : by the way :

perl -e '$_="aaaaa";print $v=(($x,$y)=split //)'

returns 3, because the right sight of the $v=... command gives :

( $x , $y , ( a , a , a ) )

So in your original case, ()=split // returns ( ( a , a , a , a , a ) ) (which has only one element)

Edit : bad array notation, and result was wrong because of a last minute changed of my test-case

Upvotes: -2

Oleg V. Volkov
Oleg V. Volkov

Reputation: 22421

According to split documentation:

When assigning to a list, if LIMIT is omitted, or zero, Perl supplies a LIMIT one larger than the number of variables in the list <...>

Since you specify empty list, split only returns 1 result and this number of results is exactly what ends in your variable.

Upvotes: 14

Tom Tanner
Tom Tanner

Reputation: 9354

Why are you assigning to an empty array? the ()=(split //) bit. That's going to end up with - um, well, a mess. Or, in your case, an array with a size of one with not much in it.

Also, that's excessively obscure. perl has a sad reputation for being write-only, and all that modifying $_ and using it doesn't help others - or you - understand what is going on.

Try something like

perl -e '$v = (split //, "aaaaa"); print "$v\n"'

or, if you wish to replicate the behavior of your test:

perl -e '$v = () = (split //, "aaaaa"); print "$v\n"'

Upvotes: -1

Related Questions