Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

shift on empty array in list context broken

by LanX (Saint)
on Jul 13, 2019 at 19:23 UTC ( [id://11102798]=perlquestion: print w/replies, xml ) Need Help??

LanX has asked for the wisdom of the Perl Monks concerning the following question:

Why does a list context shift on an empty array return (undef) ?

Shouldn't shift behave like one element splice

DB<16> @array =() DB<17> (@x) = splice @array,0,1 DB<18> x @x empty array DB<19> (@x) = shift @array DB<20> x @x 0 undef # WTF

update motivation

please note how loops over shift can't handle false values in scalar context, but become endless in list context.

This behaviour breaks conventions of other iterators ...

DB<1> @x = (1..3,0,undef,1..3) DB<2> $max=100 DB<3> while (my ($x) = shift @x) { print "$x,"; last if $max-- < 0 } 1,2,3,0,,1,2,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, DB<4> @x = (1..3,0,undef,1..3) DB<5> while (my $x = shift @x) { print "$x," } 1,2,3,

Cheers Rolf
(addicted to the Perl Programming Language :)
Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Replies are listed 'Best First'.
Re: shift on empty array in list context broken
by tybalt89 (Monsignor) on Jul 13, 2019 at 21:05 UTC

    It doesn't look like shift has a list context, at least according to perldoc. That makes some sense, since it can only return one thing, unlike splice, which can return zero to many.

    I'd use

    while( @x ) { print shift @x, ',' }

    for your last example.

      > It doesn't look like shift has a list context, at least according to perldoc.

      well splice also says

      The following equivalences hold
      ... shift(@a) splice(@a,0,1)

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

        splice lied! It's almost sort-of nearly true, but not completely true :)

        On the other hand, try

        my @x = (); my $x = splice @x, 0, 1;

        What splice says is true in scalar context.

        That should be fixed. Feel free to use perlbug to submit a bug report. Please include a suggested fix.

        >well splice also says
        > The following equivalences hold
        > ...
        > shift(@a)     splice(@a,0,1)

        It would appear shift is doing something like this:

        DB<232> x $x=4; while( ($y)= ( $u = splice( @t,0,1 ))){ last unless +$x--; print ":$_: " } :: :: :: :: empty array

        which would make the equivalence:

        shift(@a) === ( $t = splice( @a,0,1 ) )
Re: shift on empty array in list context broken
by ikegami (Patriarch) on Jul 15, 2019 at 11:12 UTC

    No, it shouldn't. Operators and subs that one expects to return a scalar should do so in list context too. It leads to weird and sometimes subtle (i.e. hard to debug) problems if they sometimes return an empty list instead. The purpose of shift is to return a scalar, and it should do so.

Re: shift on empty array in list context broken
by Don Coyote (Hermit) on Jul 16, 2019 at 01:32 UTC

    shift may not be the culprit, if you look at how the assignment is evaluated. Both the scalar and array assignment are evaluated in scalar context

    DB<41> x { $max=100; while ( () = undef ) {print "$x, "; last if $ +max-- == 0 } } , , , , , , , , , , , , , , , ... , , , , , , , , , , , , , , , , , , +, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , + , , , , , , , , , , , empty array DB<42> x { $max=100; while ( $_ = undef ) {print "$x, "; last if $ma +x-- == 0 } } 0 undef

    I dont know if this might be affecting how shift is working, but may shed some light.

    I did investigate the splice/shift difference a little, they behave the same when both @x and @array are undef, but different when, as you highlighted they are empty.

    Possibly shift and splice are optimised at that level due to their expected usage.

    Update: this may be something to consider.

    DB<60> x { $max=100; while ( @x = splice( @{[]},0,1 )) {print "$x, " +; last if $max-- == 0 } } 0 0 DB<61> x { $max=100; while ( @x = shift @{[]} ) {print "$x, "; last +if $max-- == 0 } } , , , , , , , , , , , , , , ... , , , , , , , , , , , , , , , , , , , +, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , + , , , , , , , empty array
      > they behave the same when both @x and @array are undef,

      not sure what you mean here...(?)

      anyway I doubt it's possible to "fix" this, much code will rely on shift returning undef.

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

        I'm not exactly sure either. I attempted to write some Test scripts. Getting only as far as comparing a couple of variations.

        heres two scripts that start out looking to compare list and scalar context asignment. I'm not sure they have picked up what you are viewing, but could possibly get there?

        A B my @x @y Scalar Context

        C D my (@x),(@y) List Context

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11102798]
Approved by holli
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (3)
As of 2024-04-19 04:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found