#perl_noob has asked for the wisdom of the Perl Monks concerning the following question:

Suppose I have some methods do_something(), do_nothing(), do_less(), do_more(),etc in a module.

The around method modifier receives a code ref to the original method as given in Moose Documentation. The same around method is for all the methods in my module. do_something() is called from my script, $orig prints a code ref address which is different from the the address I get when I directly print \&do_something inside the around method or the module or the script (uses the module).

Could someone explain me why this happens? I want to perform an additional check when $orig equals do_something() inside the around method, any suggestions on how to since $orig and \&do_something are giving different code refs.

Replies are listed 'Best First'.
Re: Code ref inside around modifier (updated)
by haukex (Archbishop) on Apr 11, 2017 at 09:26 UTC

    Instead of around ['do_something','do_otherthing'] => sub { ... }, try this, as suggested by Moose::Manual::MethodModifiers:

    for my $method ('do_something','do_otherthing') { around $method => sub { my $orig = shift; my $self = shift; print "around $method\n"; if ($method eq 'do_something') { ... } $self->$orig(@_); }; }

    Update 2: $orig and \&do_something are giving different code refs ... Could someone explain me why this happens?

    By the time the piece of code "\&do_something" is executed, do_something is already pointing to the wrapped sub do_something.

    { package Bar; use Moose; sub do_something { print "did something\n" } my $before = \&do_something; around 'do_something' => sub { my $orig = shift; my $self = shift; print "around do_something\n"; print "\t\$orig=$orig\n"; print "\t\$before=$before\n"; print "\t\\&do_something=".\&do_something."\n"; }; } my $bar = Bar->new; $bar->do_something; print "can=", $bar->can('do_something'), "\n"; __END__ around do_something $orig=CODE(0x223d5e8) $before=CODE(0x223d5e8) \&do_something=CODE(0x228ae92) can=CODE(0x228ae92)

    Update 3: A bit more explanation: Notice how $before holds the reference to the original sub do_something before it's wrapped by around, and ->can('do_something') reports the coderef of the final, wrapped method. Compare these two to $orig and \&do_something. Remember that the anonymous sub given to around doesn't get executed until the method is called, by which time it's already been wrapped, at which time \&do_something points to the wrapped method.

    Update 1: In my very first code example, added an example of checking which method is being wrapped.

      It works. Thanks a lot for the example and the explanation.

Re: Code ref inside around modifier
by shmem (Chancellor) on Apr 11, 2017 at 09:32 UTC

    To see what's going on, I'd initialize a B::Deparse object inside the around method and run a $dp->coderef2text($orig). Maybe there's an additional wrapper around the original $orig. Can't say more, since I haven't use Moose and/or Class::MOP yet.

    perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'