I have a program with a while loop which has several points where certain conditions require some action to be taken and then the remainder of the iteration to be skipped.
As this is always going to be the same code, I wanted to put it in a subroutine, but when I try using 'next;' as the final statement in the sub I get a warning (Exiting subroutine via next at ...), although it appears to work as intended.
i.e. without the sub:
while (#condition) {
## do stuff
if (#condition to skip iteration) {
## action
next;
}
## do more stuff, with the above block repeated several times
}
with sub:
while (#condition) {
## do stuff
&skip if (#condition to skip iteration);
## do more stuff, with more calls to &skip
}
sub skip() {
## action
next;
}
The rest of the code in the block/sub is so short that putting all but the next; statement in a sub pretty much defeats the object of using a subroutine.
My question is:
It's easy to suppress the warning. Just place the following line above your next
:
no warnings "exiting";
The warning is there for a reason - using next
in a helper sub like that can be confusing for the next person who has to read the code (who might be you in 6 months' time!) because the next
does not occur lexically within the loop block. If you're just reading the loop block, you might not notice that next
further down the file; and if you're just reading the definition of the subroutine, you might not be sure what that next
is for. You need to read both parts of the code together to make sense of it. That makes it more confusing than using next
directly inside the loop.
Also, it limits the re-usabilty of the skip()
sub you've just defined. Want to re-use that skip()
sub inside another loop? You'd better hope that the skip logic still makes sense in the new loop.
If you've considered all that and still want to go ahead, then just disable the warning as I showed above. Warnings are not errors, they're just warnings. That's why warnings are called "warnings". They're designed to bring your attention to something potentially problematic; not to stop you from doing something you've decided is useful.
From the Learning perl 6th edition page 179 (footnote)
It’s probably not a good idea, but you could use these loop-control operators from inside a subroutine to control a loop that is outside the subroutine. That is, if a subroutine is called in a loop block, and the subroutine executes last when there’s no loop block running inside the subroutine, the flow of control will jump to just after the loop block in the main code. This ability to use loop control from within a subroutine may go away in a future version of Perl, and no one is likely to miss it.
The solution could be what others already said, or you can do additional test in the sub, like
use strict;
use warnings;
while(<>) {
chomp;
maybeskip($_) && next if m/2/; #maybe skip if match 2
print "$_\n";
}
sub maybeskip {
$_[0] !~ m/0/; #skip only if not match 0
# the sub retuns the result of the last executed expression
# if this is not wanted you should use explicit return $value;
}
for the
seq 25 | perl script
prints:
1
3
4
5
6
7
8
9
10
11
13
14
15
16
17
18
19
20
e.g. skipped all matched 2
but not 20
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With