避免在布尔上下文中grepping all

时间:2017-11-21 15:32:05

标签: perl grep

perl中的grep函数无法识别“boolean”上下文,因为在Perl中根本没有“布尔”上下文。

所以,如果我做这样的事情

print "matched\n" if grep { print "$_\n"; $_&1 } 1..31

将打印从1到31的数字,而不是仅打印“1”,这足以在“if”中获得“true”结果。

为了避免这种行为,我必须做一些可怕的事情:

print "matched\n" if do { my $fl; $_&1 and $fl=1, last for 1..31; $fl }

也许可以用最简单的方式完成?是否有一些在CPAN上实现“布尔grep”的快速XS代码?

3 个答案:

答案 0 :(得分:5)

每个人似乎都忘记了他们可以编写潜艇以隐藏“糟糕”的细节。

sub any(&@) { my $cb = shift; for (@_) { return 1 if $cb->() } 0 }

say "match" if any { say; $_ & 1 } 1..31;

尽管如此,any已由List::Util提供。 (另请查看List::MoreUtils。)

请注意,在调用any之前,迭代的项目列表仍将完全放在堆栈上。与不必要多次调用sub相比,这相当便宜,但它仍然可能是一个问题。我认为这是List::Gen试图解决的问题。

答案 1 :(得分:0)

这听起来像是寻找工作的工具而不是寻找工具的工作。如果任务是通过一个数字列表并在找到符合条件的数字时停止,请不要使用设计想要检查每个元素的内容:

cache-control

答案 2 :(得分:0)

grep能够作弊;它执行的块实际上并不是一个子程序,并且能够以比它更快的速度运行它,并且非grep替代方案被卡住进行子调用。

IMO,除非你有一个很长的列表并且很可能在开始时找到所需的匹配,所以没有理由不使用grep。或者至少,让你的代码更具可读性的原因(使用"任何"或者这样做)可以超过任何性能增益(或损失)。