Do something after sub foo in Perl?
after foo 开发者_如何学Go=> sub{
...
}
I just stumble upon code like above, which is called after sub foo
finishes,
how does that work?
It seems it's not built-in feature of Perl,right?
It's one of the Moose method modifiers.
Method modifiers can be used to add behavior to methods without modifying the definition of those methods.
Out of curiosity, I've tried to do it myself, and got code that works to some extent (no list context, no corner cases etc.).
Perl allows for horrible things.
% perl -wle 'use After; sub foo { $_[0] * 2};
after foo => sub { print $_[0] }; foo(5); foo(6);'
10
12
Here's After.pm. Please don't ever use it.
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;
It is not a builtin feature as others have already stated. For programs that do not use Moose
, you can use Class::Method::Modifiers
to get these modifiers.
If after
is a predeclared subroutine, it would mean that you call that sub, with foo
and an anonymous sub as arguments. It does seem a bit odd, though.
=>
is equivalent to a comma, so assuming after
is a sub, it would mean this:
after('foo', sub { ... });
精彩评论