Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

why can't I shift a split?

by Anonymous Monk
on Aug 25, 2022 at 14:22 UTC ( [id://11146414]=perlquestion: print w/replies, xml ) Need Help??

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

why does
$_='something,something else'; @_ = shift split /,/;
yield this error:  Not an ARRAY reference

I sorta get that shift is an operator that changes its arg, but doesnt "return" the result. So, why does this ALSO not work:

$_='something,something else'; shift ( @_ = split /,/ );
(all result in the same error).

It seems like "some" construct of shifting a split should work? Help please Blessed Ones! Surely the LAST one should be an ARRAY!?

It "seems" natural that Larry would have intended to allow cascading operators like these?

Replies are listed 'Best First'.
Re: why can't I shift a split?
by ikegami (Patriarch) on Aug 25, 2022 at 15:36 UTC

    shift requires an array (@NAME, @BLOCK, EXPR->@* and similar).


    You want a list slice (( LIST )[ INDEXES ]).

    Specifically,

    ( split( /,/, $_, 2 ) )[ 0 ]

    If you are assigning the result to a scalar, you can also use

    my ( $first ) = split( /,/, $_, 2 );

    Using 2 for split's third operand isn't required; it's an optimization. There's no reason to continue splitting after the first split.

Re: why can't I shift a split?
by Tux (Canon) on Aug 25, 2022 at 15:43 UTC

    To me, it is not clear what you want at all. Do you want the result of the split excluding the first element in @_? Or do you want @_ only hold the first element and discard the rest?

    $ perl -E'$a="a,b,c,d";(undef,@_)=split/,/,$a;say "@_"' b c d $ perl -E'$a="a,b,c,d";@_=(split/,/,$a,2)[0];say "@_"' a

    Enjoy, Have FUN! H.Merijn
Re: why can't I shift a split?
by kcott (Archbishop) on Aug 25, 2022 at 15:27 UTC

    Take a look at shift. It says "shift ARRAY", not "shift LIST".

    Look down to the nextsecond paragraph where it talks about an experimental feature that's been removed. I'm guessing the version of Perl you're using is >=v5.14 and <v5.24: so it's trying to use that experimental feature but failing because "( @_ = split /,/ )" is not an array, nor does it evaluate to an arrayref.

    You can try the following with your version of Perl. I don't have a version earlier the v5.30, so I get:

    $ perl -MO=Deparse -e 'shift ( @_ = split /,/ )' Experimental shift on scalar is now forbidden at -e line 1, near "/,/ +) " -e had compilation errors. shift(@_ = split(/,/, $_, 0));

    — Ken

      That's an assignment, not an array. The closest valid code is

      shift @{ @_ = split /,/; \@_ }

      There's no need to use named array, though.

      shift @{[ split /,/ ]}

      But I'd use a list slice, as shown in my reply to the OP.

Re: why can't I shift a split? (List vs Array)
by LanX (Saint) on Aug 25, 2022 at 23:25 UTC
    The fundamental problem here is that lists and arrays are two different things. That's a FAQ

    Lists are temporary data sequences which can't be changed!

    But Arrays are variable(s) with @sigils and they are changed.

    Shift can only operate on arrays, because they are shortened afterwards.

    Once you've understood this...

    > why can't I shift a split?

    Because split returns a list!

    Unless you assign it to an array it can't be shifted.

    Addendum

    Others have shown solutions with (lists)[slices] which work similar to @array[slices] . That's only possible because a slice doesn't change its object, unlike shift.

    Further reading

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

      Rolf yes, I know that- but it should be EZ to coerce a list into an array?
        > should be EZ to coerce a list into an array

        sure:

        DB<2> p shift @{[42..59]} 42

        or

        DB<3> $shift = sub { shift @{$_[0]} } DB<4> p [42..59]->$shift 42

        but it doesn't make sense since the resulting shortened array is destroyed right away.

        Using a list slice is the logical° and easiest approach, without wasting operations.

        DB<5> p (42..59)[0] 42

        compare an array slice which wastes resources again, by allocating an array in memory which is destroyed again.

        DB<6> p [42..59]->[0] 42

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery

        °) and "implementing" pop list is symmetrical (42..59)[-1]

Re: why can't I shift a split?
by afoken (Chancellor) on Aug 25, 2022 at 15:42 UTC
    $_='something,something else'; @_ = shift split /,/;

    So you want to split at comma, but get only the first part?

    use strict; use warnings; use v5.12; (my $first,undef)=split /,/,'foo,bar',2; say $first;

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
Re: why can't I shift a split?
by harangzsolt33 (Chaplain) on Aug 26, 2022 at 01:09 UTC
    It's funny, I was trying to explain why it's not working, and I got really confused myself! LOL Here's what I began to write:

    When you do shift split, the shift() function not only returns the first element of an array, but it also tries to REMOVE that element from an array, which it must be able to do. Demo:

    #!/usr/bin/perl use strict; use warnings; my @A = (234, 405, 55, 1900); print "\n", shift(@A); # Prints 234 #print "\n", shift(234, 4, 55, 1900); # Error: Can't overwrite +the array, because it's fixed. #print "\n", shift( split(/\+/, '12+34+56+78') ); # Error: Can't over +write the array, because it's fixed. my $X = 3; print "\n", INCREMENT($X); # Prints 4. #print "\n", INCREMENT(3); # Error: Can't overwrite 3, because it's + fixed. print "\nNOW: $X"; # Prints 4. No error. print "\n", INCREMENT( $X + 3 ); # Prints 8. No error. print "\nTHEN: $X"; # Prints 4. No error. #print "\n", shift( @A, split(/\+/, '12+34+56+78') ); # Error. Can't +do this. # Kind of weird. That's not what I expected. :P exit; sub INCREMENT { ++$_[0]; }

    See also: lvalue

      #print "\n", shift(234, 4, 55, 1900);        # Error: Can't overwrite the array, because it's fixed.

      shift works by default on @_ in a subroutine (also true of pop) so you could use an on-the-fly sub to operate on a list.

      johngg@aleatico:~$ perl -Mstrict -Mwarnings -E ' my @arr = ( 234, 405, 55, 1900 ); say shift @arr; say sub { shift }->( 234, 405, 55, 1900 ); $_ = q{ab,ce ef}; say sub { shift }->( split m{,} );' 234 234 ab

      I hope this is helpful.

      Update: Corrected typo, s{on (?=by default)}{}.

      Cheers,

      JohnGG

Re: why can't I shift a split?
by misterperl (Pilgrim) on Aug 25, 2022 at 14:27 UTC
    Oh drat I wasn't logged in! I also tried this fugly one:
    $_='something,something else'; @_ = shift @ {split /,/ };
    which is OK syntax wise, but results in "undef".

      But

      $_='something,something else'; @_ = shift @ {[split /,/ ]};
      does work.

        TY Kind and Wise Monks for these replies. Ken- it's reassuring to know that at least in some Perl-verse this is legal or at least considered.

        What I'm seeking is the LAST array element; I want shift to toss the top one.

        this is similar to something else I often do successfully:

        @_ = split /,/,join "\n",$myscalar
        I was trying to do something similar with shift.. I also tried
        shift @_ = split /,/,join "\n",$myscalar
        Which I thought had the best chance. Mr TVVALUT has a solution I'll try... I recognize the list/ARRAY difference which is why I was trying various "@{}" constructs to coerce it. Seems like if I can split a join, then I ought to be able to shift a split!

        TY all!

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (4)
As of 2024-04-19 03:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found