如何将函数传递给Perl子?

问题描述:

我该如何编写一个接受类似map函数的函数呢?如何将函数传递给Perl子?

例子:

$func = sub { print $_[0], "hi\n" }; 
&something($f); 
sub something 
{ 
    my $func = shift; 
    for ($i = 0; $i < 5; $i++) 
    { $func->($i); } 
} 

工作正常。

但当时如果我没有

&something({ print $_[0], "hi\n" }); 

它不会工作,并说FUNC是一个未定义的参考。

所以我的问题是我将如何编写一个函数,接受参数像perls map函数?

map { s/a/b/g } @somelist; 

map功能具有非常神奇的语法,你可能不希望除非你有一个很好的理由将它复制;只是使用普通的无名子,是这样的:

something(sub { print $_[0], "hi\n" }); 

如果你真的想这样做,不过,你需要使用prototype

sub my_map (&@) { 
    my ($func, @values) = @_; 
    my @ret; 
    for (@values) { 
     push @ret, $func->($_); 
    } 
    return @ret; 
} 

my @values = my_map { $_ + 1 } qw(1 2 3 4); 
print "@values"; # 2 3 4 5 

(注意:$_动态范围的,所以任何值已在来电者的功能被保留。)

List::UtilList::MoreUtils做这样的事情很多创建外观内置功能和行为像的变种10/grep。这真的是唯一的情况下应该使用这样的东西。

+0

+1。我喜欢用“for”语句对$ _进行本地化的想法 - 允许1-arg funcrefs变得简洁明了。 (我想你可以“本地($ a,$ b);”对于2-arg funcrefs la sort()。) – 2009-08-22 18:06:59

&something({ print $_[0], "hi\n" }); 
#   ^^^ this isn't a reference 

&something(sub { print $_[0], "hi\n" }); # works just fine 
+0

为什么你有'&'放在前面? – 2009-08-21 16:58:28

+0

大概是因为OP有一个,答案是复制OP的风格。即使前缀可能不应该在那里,正如SinanÜnür解释的那样。 – 2009-08-21 17:22:37

首先,在拨打sub s时不要使用&。从perldoc perlsub

子程序可以递归调用。如果使用&表单调用子例程,则参数列表是可选的,如果省略,则不会为该子例程设置@_数组:调用时该数组的@_对子例程可见。这是新用户可能希望避免的效率机制。

如果你希望能够通过一个简单的块“sub something”,您需要使用的原型为:

sub something(&@); 

# later 

sub something(&@) { 
    my ($coderef, @args) = @_; 

} 

Prototypes

我个人只想传递一个明确的子参考:

something(sub { });