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

This is a question of style.

So far I have only used "last" in a block preceded by "for" or "while", but it seems that you can use last in any block with the effect that the remainder of the block is skipped.

So for example this works:

if($some_condition) { open my $fh, "<", "some_file" or last; # do something with $fh here if the open was successful # if the open fails we skip this part } do_something_else();
What would you say? Is this an acceptable (even idiomatic use of "last") or just a hack that should be avoided?

Replies are listed 'Best First'.
Re: use of last
by Eily (Monsignor) on Jul 20, 2015 at 08:20 UTC

    Actually last will only work on loops. A single block, without any kind of flow control (if, do while, for) counts as a loop that executes only once. So

    { open my $fh, "<", "some_file" or last; }
    Will work, and you can make it work with your code by doubling the curly brackets:
    if (/VALID/) {{ # First bracket is for the if, second is for a loop-like block open my $fh, "<", "some_file" or last; }}

    last will never allow you to exit an if-block, because it is often used in constructs such as:

    while (<>) { if (/INVALID/) { last; } }
    Note that it's always possible to name the while loop to provide the name to last and make it clearer what you are leaving.

    Edit: completed my last sentence (apparently I forgot what I was saying mid-sentence), and added a condition after the if, so that the code doesn't look so odd.

    Edit: BTW, I think that karlgoethebier's version is easier to read.

Re: use of last
by karlgoethebier (Abbot) on Jul 20, 2015 at 08:22 UTC

    You can put it in a block...

    KARL: { if ($x) { $y or last; print "Continue with the if clause\n"; } }

    ...if you really need it.

    Regards, Karl

    «The Crux of the Biscuit is the Apostrophe»

Re: use of last
by Athanasius (Archbishop) on Jul 20, 2015 at 08:07 UTC

    Hello morgon,

    It doesn’t work for me (Strawberry Perl running under Windows 8.1, 64-bit):

    use strict; use warnings; my ($x, $y) = (1, 0); if ($x) { $y or last; print "Continue with the if clause\n"; } print "Do something else\n";

    Output:

    18:04 >perl 1312_SoPW.pl Can't "last" outside a loop block at 1312_SoPW.pl line 8. 18:04 >perl -v This is perl 5, version 22, subversion 0 (v5.22.0) built for MSWin32-x +64-multi-thread

    I get the same result with next.

    What version of Perl are you using?

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      It is getting stranger...

      Your code does not work for me as well, however this does:

      use strict; use warnings; my ($x, $y) = (1, 0); if ($x =~ /whatever/) { $y or last; print "Continue with the if clause\n"; } print "Do something else\n";
      Probably in your case the optimizer is too smart ...

      I am using 5.18.1 on Debian.

      UPDATE: I was wrong. If you change the regex to !~ (so that the condition is true) you get the same error.

Re: use of last ( is goto, bare blocks aren't loops)
by Anonymous Monk on Jul 20, 2015 at 10:09 UTC
Re: use of last
by Anonymous Monk on Jul 20, 2015 at 16:14 UTC
    Since it is not what I would expect, it is not what I would do.
Re: use of last
by james28909 (Deacon) on Jul 20, 2015 at 15:27 UTC
    why not use a while loop like:
    my $x = 'FALSE'; while ( $x ) { $x = 'TRUE'; last if( $x =~ /TRUE/ ); } print 'Script is now outside of while loop and $x is TRUE';
Re: use of last
by james28909 (Deacon) on Jul 20, 2015 at 15:27 UTC
    why not use a while loop like:
    my $x = 'FALSE'; while ( $x ) { $x = 'TRUE'; last if( $x =~ /TRUE/ ); } print 'Script is now outside of while loop and $x is TRUE';
    But without seeing more code in which this question was derived from, I am not certain this will be what you need. You may not need a while loop.

      why not use a while loop like:

      Why not a simple if statement

      if( ! $true ){ ## skip after "last" ...; }