简体   繁体   English

如何将函数传递给Perl子?

[英]How can I pass a function to a Perl sub?

How would I write a function that accepts something like the map function does? 我怎么写一个接受像map函数那样的函数呢?

Example: 例:

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

works fine. 工作正常。

but then if I did 但是如果我这样做的话

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

it wont work and says func is an undefined reference. 它不会工作,并说func是一个未定义的参考。

So my question would be how would I write a function that accepts parameters like perls map function? 所以我的问题是如何编写一个接受perls map函数等参数的函数?

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

The map function has very magical syntax, and you probably don't want to copy it unless you have a really good reason; map函数具有非常神奇的语法,除非你有充分的理由,否则你可能不想复制它。 just use a regular anonymous sub, like this: 只需使用常规的匿名子,如下所示:

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

If you really want to do this, though, you need to use a 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

(Note that $_ is dynamically scoped, so whatever value it has in the caller is preserved in the function.) (注意$_是动态范围的,因此它在调用者中的任何值都保留在函数中。)

List::Util and List::MoreUtils do this sort of thing a lot to create functions that look built-in and act like variants of map / grep . List::UtilList::MoreUtils做了很多这样的事情来创建看起来内置的函数,并且像map / grep变体一样。 That's really the only case where something like this should be used. 这是唯一一个应该使用这种东西的情况。

First off, do not use & when calling sub s. 首先,在调用sub时不要使用& From perldoc perlsub : 来自perldoc perlsub

Subroutines may be called recursively. 子程序可以递归调用。 If a subroutine is called using the & form, the argument list is optional, and if omitted, no @_ array is set up for the subroutine: the @_ array at the time of the call is visible to subroutine instead. 如果一个子程序使用被叫&形式,参数列表是可选的,如果省略,没有@_阵列设置为子程序:在@_数组在调用的时候是可见的,而不是子程序。 This is an efficiency mechanism that new users may wish to avoid. 这是新用户可能希望避免的效率机制。

If you want to be able pass a plain block to " sub something ", you need to use a prototype as in: 如果您希望能够将普通块传递给“ sub something ”,则需要使用原型,如下所示:

sub something(&@);

# later

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

}

See Prototypes . 请参阅原型

I personally would just pass an explicit subref: 我个人只会传递一个明确的subref:

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM