在Perl中使用sub foo后做一些事情?

时间:2011-08-23 05:39:44

标签: perl

after foo => sub{
    ...
}

我只是偶然发现了上面的代码,这些代码在sub foo完成后调用,

这是如何运作的?

似乎它不是Perl的内置功能,对吗?

4 个答案:

答案 0 :(得分:5)

这是Moose method modifiers之一。

  

方法修饰符可用于向方法添加行为,而无需修改这些方法的定义。

答案 1 :(得分:3)

出于好奇,我试图自己做,并获得在某种程度上有效的代码(没有列表上下文,没有角落案例等)。

Perl允许可怕的事情。

% perl -wle 'use After; sub foo { $_[0] * 2}; 
    after foo => sub { print $_[0] }; foo(5); foo(6);'
10
12

这是After.pm。请不要 使用它。

use warnings;
use strict;

package After;

# make after() available after 'use After;'
use Exporter;
BEGIN {
    our @ISA = qw(Exporter);
    our @EXPORT = qw(after);
};

# prototype: bareword + sub
sub after (*&) {
    my ($name, $code) = @_;
    my $caller = caller; # get calling package

    # fetch old sub named "name" 
    # note $oldcode = *{...} is not ehough 
    my $oldcode;
    {
        no strict 'refs';
        $oldcode = \&{$caller."::".$name};
    };

    # defined new sub
    my $newcode = sub {
        my $ret = $oldcode->(@_);  # call old sub as is
        $code->($ret);             # call the after sub
        return $ret;               # ignore aftersub's ret val
    };

    # plant new sub into the calling package
    # avoid redefinition warnings 
    {
        no strict 'refs';
        no warnings 'redefine';
        *{$caller."::".$name} = $newcode;
    };
};

1;

答案 2 :(得分:3)

这不是其他人已经说过的内置功能。对于不使用Moose的程序,您可以使用Class::Method::Modifiers来获取这些修饰符。

答案 3 :(得分:1)

如果after是预先声明的子例程,则意味着您使用foo和匿名子作为参数调用该子。但这确实有点奇怪。

=>相当于一个逗号,因此假设after是一个sub,则意味着:

after('foo', sub { ... });