This one just came up: How do I break out of an if statement? I have a long if statement, but there is one situation where I can break out of it early on.
In a loop I can do this:
while (something ) {
last if $some_condition;
blah, blah, blah
...
}
However, can I do the same with an if statement?
if ( some_condition ) {
blah, blah, blah
last if $some_other_condition; # No need to continue...
blah, blah, blah
...
}
I know I could put the if statement inside a block, and then I can break out of the block:
{
if ( some_condition ) {
...
last if $some_other_condition; # No need to continue...
blah, blah, blah
...
}
}
Or, I can create a subroutine (which is probably better programmatically):
if ( some_condition ) {
run_subroutine();
}
sub run_subroutine {
blah, blah, blah
return if $some_other_condition;
blah, blah, blah
...
}
But is there any way to exit an if condition?
Resolution
The question came up because I was helping someone with their code. Inside a fairly long if statement, there were several other if statements embedded in it. The code looked something like this:
if ( $condition1 ) {
blah, blah, blah;
if ( not $condition2 ) {
blah, blah, blah;
if ( not $condition3 ) {
blah, blah, blah;
}
}
}
I thought the whole thing could be made more readable by doing this:
if ( $condition1 ) {
last if $condition2;
blah, blah, blah;
last if $condition3;
blah, blah, blah;
}
This shows that the normal flow of the if statement is standard, but under certain conditions, the if statement was exited early -- much like using last or next in a while or for loop to exit the loop.
I liked mpapec's solution of using a label -- even if I don't use the label itself. The label is a description of my if:
IF-UNDER-CONDITION1:
{
if ( $condition1 ) {
last if $condition2;
blah, blah, blah;
last if $condition3;
blah, blah, blah;
}
}
Although it isn't a standard coding technique, the flow of the code is obvious enough that a typical low-level Perl developer (the one that has to maintain this code after I leave) could figure out what the code is doing and maintain it. They may even learn something in the process.
You can use basic block which is subject to last, next and redo, so there is possible break from it.
if ($condition) {EXIT_IF:{
last EXIT_IF; # break from code block
print "never get's executed\n";
}}
EXIT_IF: {
if ($condition) {
last EXIT_IF; # break from code block
print "never get's executed\n";
}
}
Put it inside an empty
for()loop, and addlast;everywhere you want to break out AND after theif. A bit ugly but works. Make sure to add comments to explain the trick.for (;;) { if (condition) { #code last if another_condition; } last; }use
gotoand label a statement after your loop for that goto. Be forever damned.Extra block inside the
if(e.g.if () {{ code }}). May be hard to read for novices but OK if accompanied by a comment.your own solution: block around
if. Not very obvious readability-wise.your own solution: subroutine with return.
Frankly, unless the cost of calling a sub matters performane wise, this is the cleanest solution as far as readability.
You could put the rest of your if block inside another if statement, like this:
if (some_condition) {
blah, blah, blah
if (!$some_other_condition) {
blah, blah, blah
...
}
}
Another alternative is to use an anonymous subroutine.
Note: I don't recommend this method because of the added scoping complexity (see note below); it is just for completeness of possible answers.
if( $true_condition ){
(sub{
return if $true_condition;
...
})->();
}
Note: any variables declared w/in the routine must use our instead of my if you wish to use them in the rest of the code.
I tend to use sequential if-statements based on a "do I continue?" variable instead. Your
if ( $condition1 ) {
blah, blah, blah;
if ( not $condition2 ) {
blah, blah, blah;
if ( not $condition3 ) {
blah, blah, blah;
}
}
}
can be rearranged to
my $ok = $condition1;
if ($ok) {
blah, blah, blah;
$ok = not $condition2;
}
if ($ok) {
blah, blah, blah;
$ok = not $condition3;
}
if ($ok) {
blah, blah, blah;
}
Keep your while loop so you can use last but also make sure that the loop is executed at most once
my $loop_once = 1;
while ( $loop_once-- and some_condition ) {
blah, blah, blah
last if $some_other_condition; # No need to continue...
blah, blah, blah
...
}
I was inspired by DVK's answer to play around, and I came up with this variant that works at least on Perl 5.26.1:
for( ; some_condition ; last ) {
blah, blah, blah
last if $some_other_condition; # No need to continue...
blah, blah, blah
}
Per perlsyn, this is equivalent to:
while (some_condition) {
blah, blah, blah
last if $some_other_condition; # No need to continue...
blah, blah, blah
} continue {
last;
}
In a continue block, last has the same effect as if it had been executed in the main loop. Therefore, the loop will execute zero or one times, depending on some_condition.
Tests
perl -E 'my ($cond, $other)=(X, Y);
for(;$cond;last) { say "hello"; last if $other; say "goodbye" }'
has the following results, for various X and Y values:
X Y Prints
-----------------------
0 0 (nothing)
0 1 (nothing)
1 0 hello, goodbye
1 1 hello
来源:https://stackoverflow.com/questions/17053666/perl-breaking-out-of-an-if-statement