Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
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 having an uproarious good time at the Monastery: (15)
As of 2014-11-26 15:13 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My preferred Perl binaries come from:














    Results (171 votes), past polls