代码之家  ›  专栏  ›  技术社区  ›  hillu

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

  •  26
  • hillu  · 技术社区  · 14 年前

    为了学习的目的,我在玩弄建造 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
    

    Sub中的代码是否有方法访问该代码的coderef 所以我可以不用额外的变量?我想 这样安排初次通话。

    schedule_event( sub { ... }, 0);
    

    我第一次想到用 caller(0)[3] ,但这只会给我一个 函数名,,( __ANON__ 如果没有名称),则不是代码引用 上面有个垫子。

    5 回复  |  直到 9 年前
        1
  •  14
  •   Flimm    9 年前

    __SUB__ 已经添加到5.16中,提供了这种可用性。

        2
  •  14
  •   Leon Timmermans    14 年前

    我想 Sub::Current 会解决你的问题。

        3
  •  14
  •   Eric Strom    14 年前

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

    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);
    
        4
  •  5
  •   JB.    14 年前

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

    my $cb = do {
      my $sub;
      $sub = sub { contents using $sub here }
    }
    
        5
  •  4
  •   runrig    14 年前

    使用定点组合器,可以编写$cb函数,就像第一个参数是函数本身一样:

    sub U {
      my $f = shift;
      sub { $f->($f, @_) }
    }
    
    my $cb = sub {
      my $cb = shift;
      ...
      schedule_event(U($cb), 10);
      ...
    }
    
    schedule_event(U($cb), 0);