Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

"last" not really outside loop block

by spx2 (Chaplain)
on Jun 22, 2009 at 15:38 UTC ( #773663=perlquestion: print w/ replies, xml ) Need Help??
spx2 has asked for the wisdom of the Perl Monks concerning the following question:

On this piece of code

$a = 3; do { last unless $a == 4; } while ( 1 );

I get Can't "last" outside a loop block at /tmp/test.pl line 3. Is this the expected behaviour for "last" ?

My perl version is v5.10.0 built for i486-linux-gnu-thread-multi

Comment on "last" not really outside loop block
Download Code
Re: "last" not really outside loop block
by ikegami (Pope) on Jun 22, 2009 at 15:40 UTC

    do { ... } while 1;
    is no different than
    print ... while 1;

    The while is a statement modifier. There's no loop block, and one is needed for redo, next and last to work.

    A generic solution is to add a loop. Keep in mind that a bare block is a loop that executes once.

    $a = 3; LOOP_ONCE: { do { last unless $a == 4; } while cond(); }

    The label (LOOP_ONCE:) is descriptive and not necessary.

      Yeah , that's the work-around I've used also , I didn't like it , actually I hate it , but I'll have to stick with it

        Yeah, me too. I don't know why I suggested it. Another generic solution is to change the bottom tested loop into an infinite loop.
        do { ... next if ...; # XXX ... last if ...; # XXX ... } while cond();
        becomes
        for (;;) { # for ever ... next if ...; # OK ... last if ...; # OK ... last if !cond(); }
Re: "last" not really outside loop block
by mscharrer (Hermit) on Jun 22, 2009 at 15:50 UTC
    The tricky thing here is that do { ... } while (); is not a single syntax like in C. The do {} is one statement (and not a loop, which is a little confusing) and the postfix while just repeats this like any other statement.

    Funnily, simple braces { } qualify as a 'loop' which is processed once. It can be aborted using last.

    Therefore you could use:

    $a = 3; { last unless $a == 4; redo; # if ( ... ); }
    which works without an error message. But it isn't very good style. Try to use a normal while loop instead.

    Supplement:
    The perldoc entry for do also gives you the answer and a link to alternative strategies:

    do BLOCK Not really a function. Returns the value of the last c +ommand in the sequence of commands indicated by BLOCK. When modified + by the "while" or "until" loop modifier, executes the BLOCK once before testing the loop condition. (On other state +ments the loop modifiers test the conditional first.) "do BLOCK" does not count as a loop, so the loop contro +l statements "next", "last", or "redo" cannot be used to leave or res +tart the block. See [doc://perlsyn] for alternative strategies.
      Try to use a normal while loop instead.

      I kind of need the post-condition and while only gives me pre-condition

        Try the follwing:

        Instead of:

        do { ... } while (expr);
        use:
        while (1) { ... last unless (expr); }
Re: "last" not really outside loop block
by BrowserUk (Pope) on Jun 22, 2009 at 16:25 UTC

    I don't see much value in the construct, but you can achieve your goal by adding a bare block:

    do{{ last unless $a==4 }} while 1;

    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.
      BrowserUk,
      I am parsing with my brain and not perl but something is telling me that should instead be:
      { my $a = 3; do { last unless $a == 4; } while 1; }

      The difference being that you would be escaping the block and the loop. In my brain's parsing of your version, I last outside of the loop which is still inside the block and then re-enter because of the post-fix while condition.

      Cheers - L~R

        You parsed it correct. BrowserUk made the last behave like a next.

        Right you are.

        Adding a bare block allows the use of the loop constructs, next, last & redo ansd works as expected most places, but not in this case.


        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.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (15)
As of 2014-07-24 15:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (161 votes), past polls