Not sure which loop you want to break out of? Perl v5.18 makes that easy with computed labels. The value you give next
, last
, and redo
no longer has to be a literal. You could already do this with goto
, but now you can give the loop controllers an expression.
Here’s a contrived example. While reading lines of input and breaking the lines into words, this program might encounter either skipword
or skipline
, in which case the program should do just that. The problem is that those strings refer to different loops. That’s not a problem, though:
use v5.18; LINE: while( <DATA> ) { chomp; WORD: foreach my $word ( split ) { next uc($1) if $word =~ m/\Askip(.*)/; say $word; } } __DATA__ one two three four five skipword six seven eight nine skipline forty Buster ten eleven
In the output, you don’t see skipword
, or skipline
and anything that comes after it:
% perl5.18.1 skipline.pl one two three four five six seven eight nine ten eleven
You can do this without much more work without this feature, but you have to hardcode the labels:
use v5.10; LINE: while( ) { chomp; WORD: foreach my $word ( split ) { next LINE if $word eq 'skipline'; next WORD if $word eq 'skipword'; say $word; } } __DATA__ one two three four five skipword six seven eight nine skipline forty Buster ten eleven
I don’t have a specific recommendation for using these, but the goto
case, which has been around for a long time, is much more interesting because a loop label is only one possible target. A goto
can also jump into a code reference so it already knows how to deal with an expression.
This program is a bit different because goto
only works from inside a subroutine; there’s an exta main()
here:
my $code_ref = sub { print "I'm in the anonymous sub!\n"; }; sub named_sub { print "I'm in a named subroutine!\n"; } sub main { LINE: while( <DATA> ) { chomp; goto 'LINE' if $_ eq 'skipline'; goto $code_ref if $_ eq 'coderef'; goto \&named_sub if $_ eq 'named_sub'; print "$_\n"; } } main(); __DATA__ this is line 1 here's line 2 skipline and the third line coderef fourth line named_sub
Once you goto
a subroutine reference, however, you don’t come back to the loop. The program doesn’t resume the while
after it reads the coderef
line:
$ perl5.8.9 goto.pl this is line 1 here's line 2 and the third line I'm in the anonymous sub!