Делаете что-нибудь после sub foo в Perl? - PullRequest
1 голос
/ 23 августа 2011
after foo => sub{
    ...
}

Я просто наткнулся на код, подобный приведенному выше, который вызывается после sub foo окончания,

как это работает?

Кажется, это не встроенная функция Perl, верно?

Ответы [ 4 ]

5 голосов
/ 23 августа 2011

Это один из модификаторов метода Лося .

Модификаторы методов могут использоваться для добавления поведения к методам без изменения определения этих методов.

3 голосов
/ 23 августа 2011

Это не встроенная функция, как уже заявили другие.Для программ, которые не используют Moose, вы можете использовать Class::Method::Modifiers для получения этих модификаторов.

3 голосов
/ 23 августа 2011

Из любопытства я попытался сделать это сам, и получил код, который работает в некоторой степени (без контекста списка, без угловых случаев и т. Д.).

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;
1 голос
/ 23 августа 2011

Если after является предварительно объявленной подпрограммой, это будет означать, что вы вызываете эту подпрограмму с foo и анонимной подпрограммой в качестве аргументов. Это кажется немного странным.

=> эквивалентно запятой, поэтому, если after является подпрограммой, это будет означать следующее:

after('foo', sub { ... });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...