Perl,如何创建map/grep like子例程?

Eri*_*sum 4 perl arguments

我想创建一个类似grep {} @map {} @可以处理代码和/或布尔输入的子例程.不知何故互联网没有太多的信息.

我尝试在下面创建子,但它甚至无法处理第一次测试.我收到了错误Can't locate object method "BoolTest" via package "input" (perhaps you forgot to load "input"?) at C:\path\to\file.pl line 16..

这怎么认为它是一个对象?我没有正确创建BoolTest吗?

# Example senarios
BoolTest { 'input' =~ /test[ ]string/xi };
BoolTest { $_ =~ /test[ ]string/xi } @array;
BoolTest(TRUE);

# Example subroutine
sub BoolTest
{
   if ( ref($_[0]) == 'CODE') {
       my $code = \&{shift @_}; # ensure we have something like CODE
       if ($code->()) { say 'TRUE'; } else { say 'FALSE'; }
   } else {
       if ($_[0]) { say 'TRUE'; } else { say 'FALSE'; }
   }
}
Run Code Online (Sandbox Code Playgroud)

ike*_*ami 5

要传递代码引用,可以使用以下命令:

sub BoolTest { ... }

BoolTest sub { 'input' =~ /test[ ]string/xi };
BoolTest sub { $_ =~ /test[ ]string/xi }, @array;
BoolTest(TRUE);
Run Code Online (Sandbox Code Playgroud)

map BLOCK LIST通过使用&@原型,您可以使sub具有类似的语法.

sub BoolTest(&@) { ... }

BoolTest { 'input' =~ /test[ ]string/xi };
BoolTest { $_ =~ /test[ ]string/xi } @array;
Run Code Online (Sandbox Code Playgroud)

这就造成同一匿名潜艇是比较早,所以return,last等会表现的一样,在第一个片段.

请注意,原型版本不接受

BoolTest(TRUE);
Run Code Online (Sandbox Code Playgroud)

除非你覆盖原型

&BoolTest(TRUE);
Run Code Online (Sandbox Code Playgroud)

但是你不应该指望你的来电者这样做.根据您的示例,您可以让他们使用以下内容,但第二个子可能更好.

BoolTest { TRUE };
Run Code Online (Sandbox Code Playgroud)

  • 使用原型*来验证参数*是一种不好的做法,因为原型会改变解析规则.在这种情况下,您实际上想要更改解析规则,所以一切都很好. (3认同)
  • 你的代码永远不会设置`$ _`.大概你想把它设置为`@ _`的每个剩余值(可以使用`for(@_){$ code - >()}`来完成. (3认同)
  • 这是您真正应该使用原型的情况之一. (2认同)