Из любопытства я попытался сделать это сам, и получил код, который работает в некоторой степени (без контекста списка, без угловых случаев и т. Д.).
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;