在Perl中,子例程如何获得指向自身的coderef?

hil*_*llu 26 perl

出于学习目的,我正在研究在Perl中构建事件驱动程序的想法,并注意到如果注册为事件处理程序的子例程在失败时只能为其自身安排另一个调用它可能会很好时间.到目前为止,我想出了类似的东西:

my $cb;
my $try = 3;
$cb = sub {
    my $rc = do_stuff();
    if (!$rc && --$try) {
        schedule_event($cb, 10); # schedule $cb to be called in 10 seconds
    } else {
        do_other_stuff;
    }
};
schedule_event($cb, 0); # schedule initial call to $cb to be performed ASAP
Run Code Online (Sandbox Code Playgroud)

有没有办法让sub中的代码可以访问该sub的coderef,所以我可以不使用额外的变量?我想安排这样的初始通话.

schedule_event( sub { ... }, 0);
Run Code Online (Sandbox Code Playgroud)

我首先考虑使用caller(0)[3],但这只给了我一个函数名称(__ANON__如果没有名称),而不是附加了pad的代码引用.

Leo*_*ans 14

我认为Sub :: Current将解决您的问题.


Eri*_*rom 14

要在不使用额外变量的情况下获得对当前子例程的引用,可以使用函数式编程的工具Y-combinator,它基本上抽象出创建闭包的过程.这是一个perlish版本:

use Scalar::Util qw/weaken/;

sub Y (&) {
    my ($code, $self, $return) = shift;
    $return = $self = sub {$code->($self, @_)};
    weaken $self;  # prevent a circular reference that will leak memory
    $return;
}

schedule_event( Y { my $self = shift; ... }, 0);
Run Code Online (Sandbox Code Playgroud)


Oes*_*sor 14

__SUB__ 已在5.16中添加,提供此可用性.


JB.*_*JB. 5

如果你不再改变它$cb的值,你可以使用它.如果没有,请定义一个标量来保存它,不要再次更改它.例如:

my $cb = do {
  my $sub;
  $sub = sub { contents using $sub here }
}
Run Code Online (Sandbox Code Playgroud)