Use a computed label with loop controllers

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!