从一个子程序结束一个循环迭代
我有一个while循环的程序,它有几个点,其中某些条件需要采取一些动作,然后跳过剩余的迭代。因为这将始终是相同的代码,我想把它放在一个子程序中,但是当我尝试使用'next'时,作为子文件中的最后一个语句,我得到了一个警告(通过下一个...的退出子例程),尽管它似乎按预期工作。从一个子程序结束一个循环迭代
即没有子:
while (#condition) {
## do stuff
if (#condition to skip iteration) {
## action
next;
}
## do more stuff, with the above block repeated several times
}
与子:
while (#condition) {
## do stuff
&skip if (#condition to skip iteration);
## do more stuff, with more calls to &skip
}
sub skip() {
## action
next;
}
在块中的代码的其余部分/子很短,使得将所有但下;子语句中的语句几乎无法使用子例程的对象。
我的问题是:
- 是用 '未来;'在这样的子程序中是好的,还是危险的/糟糕的做法?
- 有没有更好的方法从子程序中跳过其余的迭代?
- 如果确定并没有更好的方法,是否有办法抑制警告?
您的警告本能可能是正确的。正如你所说,next
只是不是一种嵌入子程序中的声明。即使你不喜欢它,这是几乎可以肯定更好:
while (#condition) {
## do stuff
&skip, next if (#condition to skip iteration);
## do more stuff, with more calls to &skip
}
sub skip() {
## action
}
(我正好有对非标准编程技术比较宽松的态度,特别是如果他们不滥用如果你感到强烈嵌入next
。在这种情况下,我不会和你争论,因为这是你的程序,但是,既然你已经提出了建议,我同意你的直觉,即嵌入next
可能不是一个好主意。)
如果这是一个好的做法,警告不会警告。使用你的功能,以便它返回的时间早,而不是next
。您可以检查函数的结果,并决定是否跳过下一次迭代,或无条件地跳到下一个,
use warnings;
sub foo {
print ($_, "\n");
}
for (1..10) {
foo(), next if $_ %2;;
}
从学习Perl的第六版第179页(脚注)
它可能不是一个好主意,但是你可以在子程序中使用这些循环控制 运算符来控制子程序之外的循环。也就是说,如果在循环块中调用子程序 ,并且在子程序内没有运行 的循环块时子程序最后执行,则控制流将跳转到主代码中的 循环块之后。 这种在子程序中使用来自 的循环控制的能力可能在未来版本的Perl中消失,和 可能会错过它。
的解决方案可能是什么已经说了别人,或者你可以在子做额外的测试,像
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;
}
为
seq 25 | perl script
打印:
1
3
4
5
6
7
8
9
10
11
13
14
15
16
17
18
19
20
例如跳过所有匹配的2
但不是20
这很容易抑制警告。只要将下面这行你next
以上:
no warnings "exiting";
的警告是有原因的 - 在一个辅助子使用next
一样,可以是谁拥有读码旁边的人混乱(谁可能是你在6个月的时间!),因为next
不会出现在循环块的词汇中。如果您刚刚读取循环块,则可能没有注意到该文件后面的next
;如果您只是阅读子例程的定义,则可能不确定next
的用途。您需要将两部分代码一起阅读才能理解它。这使得它比直接在循环内部使用next
更令人困惑。
此外,它限制了您刚刚定义的skip()
子版的重用性。想要在另一个循环内重新使用那个skip()
子?你最好希望跳跃逻辑在新循环中仍然有意义。
如果你已经考虑了所有这些,并且仍然想继续,那么就像我上面显示的那样禁用警告。 警告不是错误,它们只是警告。这就是为什么警告被称为“警告”。它们旨在将您的注意力引向潜在的问题;不要阻止你做出你认为有用的事情。
可以通过将truthy返回到next
并假装继续使用and
运算符来将部分/全部跳过条件放入子例程中。
while (#condition) {
## do stuff
&skip and next if (#condition to skip iteration);
## or like this
next if (#condition to skip iteration) and &skip;
## or like this
(#condition to skip iteration) and &skip and next;
## do more stuff, with more calls to &skip
}
sub skip() {
## action
return $common_skip_condition;
}
为什么在子跳过时使用圆括号?无需在这里使用原型或签名。也许不那么容易混淆删除它们。 – jmmeier 2014-09-14 14:33:12