我有一个带有while循环的程序,它有几个点,某些条件需要采取某些操作,然后跳过剩余的迭代。
因为这总是相同的代码,我想把它放在子程序中,但当我尝试使用'next;'时作为子中的最后一个语句,我得到一个警告(通过下一个在......退出子程序),虽然它似乎按预期工作。
即。没有子:
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;
}
块/ sub中的其余代码非常短,除了下一个之外的其他所有代码; sub中的语句几乎违背了使用子程序的目的。
我的问题是:
答案 0 :(得分:8)
很容易抑制警告。只需将以下行放在next
:
no warnings "exiting";
警告是有原因的 - 在帮助程序子中使用next
可能会让下一个必须阅读代码的人感到困惑(可能是6个月后的人!)因为next
不会在循环块内以词汇方式出现。如果您只是阅读循环块,您可能不会注意到文件中的next
;如果你只是阅读子程序的定义,你可能不确定那是next
的用途。您需要一起阅读代码的两个部分才能理解它。这比在循环中直接使用next
更令人困惑。
此外,它限制了您刚刚定义的skip()
子的重新可用性。想在另一个循环中重用那个skip()
sub?你最好希望跳过逻辑在新循环中仍然有意义。
如果您已经考虑了所有这些但仍想继续进行,那么只需禁用上面显示的警告即可。 警告不是错误,它们只是警告。这就是为什么警告被称为“警告”。它们旨在引起您对潜在问题的关注;不要阻止你做你认为有用的事情。
答案 1 :(得分:6)
来自 Learning perl第6版第179页(脚注)
这可能不是一个好主意,但你可以使用这些循环控制 从子程序内部的操作符来控制外部的循环 子程序。也就是说,如果在循环块中调用子例程, 当没有循环块运行时,子程序最后执行 在子程序内部,控制流将跳转到刚刚之后 主代码中的循环块。 这种使用循环控制的能力 在子程序中可能会在未来的Perl版本中消失,而不是 一个人可能会错过它。
解决方案可能是其他人已经说过的,或者你可以在sub中进行额外的测试,比如
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
e.g。已跳过所有匹配的2
,但未跳过20
答案 2 :(得分:4)
你的警告本能可能是对的。如你所说,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
可能不是一个好主意。)
答案 3 :(得分:3)
如果这是一个好习惯,警告不会发出警告。使用您的函数,使其早期返回而不是next
。您可以检查功能结果并决定是跳到下一次迭代,还是无条件跳到下一次,
use warnings;
sub foo {
print ($_, "\n");
}
for (1..10) {
foo(), next if $_ %2;;
}
答案 4 :(得分:3)
您可以将部分/全部跳过条件放入子例程中,将truthy返回到next
并使用false {0}继续使用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;
}