Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

arrays: shifting in while loop

by ivanthemad (Initiate)
on Mar 06, 2012 at 14:30 UTC ( [id://958082]=perlquestion: print w/replies, xml ) Need Help??

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

Most mystical of monks, I seek your wisdom today regarding what is undoubtedly an imperfect understanding of Perl arrays. I have an array of integers, and I would like to pair every two integers. Perhaps I should simply use a for-loop, but I am curious as to why my first solution does not work.
use strict; use warnings; my $s = "foo bar baz qux 3 3 1 3"; my @a = split /\s/, $s; splice(@a, 0, 4); while (@a) { print (shift @a), (shift @a), "\n"; }
My understanding is that the while will execute so long as there are elements in @a, and that shift will return the left-most element of the array, move all elements down by one, and shorten the array by one. I expected to receive as output:
33 13
But instead received:
31 # and no newline!
Please direct this flummoxed novice to an explanation which said novice failed to find via either RTFM or STFW. I would be most grateful!

Replies are listed 'Best First'.
Re: arrays: shifting in while loop
by BrowserUk (Patriarch) on Mar 06, 2012 at 14:39 UTC

    This is how Perl is interpreting the critical line of your code:

    C:\test>perl -MO=Deparse,p -e" print (shift @a), (shift @a), "\n";" print(shift @a), shift @a, \'n'; -e syntax OK

    As you can see, only the first parameter is being passed to print.

    If you add another set of parens:

    print( (shift @a), (shift @a), "\n" );

    Or drop the parens entirely:

    print shift @a, shift @a, "\n";

    Your code will (probably) work as you expect.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

    The start of some sanity?

      Thank you, you are correct! Re-examining my code in the interim between posting and your timely response, I noticed that I was in fact receiving a warning:
      print (...) interpreted as function at - line 7.
      Thank you for the clear explanation which has rectified my misunderstanding! I will also examine further your use of -MO=Deparse,p -e, which looks to be very useful indeed.

        When you get a message like "print (...) interpreted as function ...", you can typically disambiguate your statement for Perl by simply adding a + in front of the opening parenthesis.

        Your original code runs like this:

        ken@ganymede: ~/local/bin $ perl -Mstrict -Mwarnings -E 'my $s = "foo bar baz qux 3 3 1 3"; my @ +a = split /\s/, $s; splice(@a, 0, 4); while (@a) { print (shift @a), +(shift @a), "\n"; }' print (...) interpreted as function at -e line 1. Useless use of a constant ( ) in void context at -e line 1. 31ken@ganymede: ~/local/bin $

        Adding a single + (changing ... print (... to ... print +(...), you get the output you were after:

        ken@ganymede: ~/local/bin $ perl -Mstrict -Mwarnings -E 'my $s = "foo bar baz qux 3 3 1 3"; my @ +a = split /\s/, $s; splice(@a, 0, 4); while (@a) { print +(shift @a), + (shift @a), "\n"; }' 33 13 ken@ganymede: ~/local/bin $

        This is discussed in more detail in perlop - Symbolic Unary Operators.

        -- Ken

        Do note you only get said warning because you use exactly one space between print and the parenthesis. Drop the space, use 2 spaces, or a tab, and the warning disappears. Replace print by warn, and the warning disappears as well.
Re: arrays: shifting in while loop
by kcott (Archbishop) on Mar 06, 2012 at 14:52 UTC

    I see you got your answer as to what was happening in your code snippet from BrowserUk.

    I don't know what context you want to use this in but the pairwise() function in List::MoreUtils may be helpful.

    -- Ken

Re: arrays: shifting in while loop
by AnomalousMonk (Archbishop) on Mar 06, 2012 at 21:36 UTC
    My understanding is that the while will execute so long as there are elements in @a...

    ivanthemad: I expect you already understand the following point perfectly well, but I want to dispell my sneaking suspicion of a possible misapprehension on your part.

    The while-loop in the example code will only begin execution (Update: of a loopthe loop body) if the array is non-empty. However, (Update: once begun) looploop body execution will continue regardless of the state of the array unless an explicit loop exit is made conditional upon array state, e.g., with a statement like  last unless @a;.

    Update: Clarified (hopefully) pertinence to loop body per repellent.

        ... loop execution will continue regardless of the state of the array unless an explicit loop exit is made ...

      Hmm, really? I always thought the while-loop EXPR was re-evaluated after each iteration:
      my @a = (3, 4); while (do { say "yo"; @a }) { say "hi mom"; shift @a; # no explicit loop break out } say "bye mom"; __END__ yo hi mom yo hi mom yo bye mom
        ... the while-loop EXPR [is] re-evaluated after each iteration...

        It is, but I was trying to make a (perhaps rather trivial) point with regard to continued execution of the loop body (which I've tried to clarify in the original reply) as exemplified below.

        >perl -wMstrict -le "my @ra = (9, 8, 7); ;; while (@ra) { print 0+@ra, ' in @ra'; shift @ra; print 0+@ra, ' in @ra'; shift @ra; print 0+@ra, ' in @ra'; shift @ra; print 0+@ra, ' in @ra'; shift @ra; print 0+@ra, ' in @ra'; shift @ra; print 0+@ra, ' in @ra'; } " 3 in @ra 2 in @ra 1 in @ra 0 in @ra 0 in @ra 0 in @ra

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://958082]
Approved by BrowserUk
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: (5)
As of 2024-03-28 21:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found