Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Re: Package level scope callbacks.

by ambrus (Abbot)
on Aug 01, 2004 at 14:48 UTC ( [id://379080]=note: print w/replies, xml ) Need Help??


in reply to Package level scope callbacks.

If I understand you correctly, you want to trap each entry and exit to the subroutines of a certain package.

As theorbtwo has noted, you can trap each and every subroutine call that happens in perl with &DB::sub, and then you check for the called package. A small example is (for perl 5.8.2)

BEGIN { sub DB::sub { my ($r, @r, $s); $s = $DB::sub; $s=~/^T::/ or goto &$s; warn "entering $s\n"; if (wantarray) { @r = &$s; } elsif (defined wantarray) { $r = &$s; } else { &$s; } warn "exitting $s\n"; wantarray ? @r : $r; } $^P |= 1; } { package T; $r = "r"; sub f { $_[0].$r.n(); } sub n { @l = l(); 2, chr(@l); } sub l { -5..4; } } sub g { T::f($_[0]."a"); }; print g("b");
(Thanks to wog for bringing $^P in my attention in Re^2: How's your Perl? (II).)

The above aspect, however, has some problems. It might be slow as it has to catch all subroutine calls, not only those in a certain package, it does not work for anonymous subs, and it might be difficult to make it work if you use the perl debugger or use DB::sub for any other purpose.

As a different approach, you could replace each subroutine in the package with a different subroutine. This, however, has the backdraw that the subroutines you want to trap have to be defined by the time you install the trapping code, as a special case you can not trap AUTOLOADED subs this way. An example is:

{ for $n (keys %T::) { if (defined &{$T::{$n}}) { my $s = $n; my $f = \&{$T::{$n}}; $T::{$n} = sub { my ($r, @r); warn "entering $s\n"; if (wantarray) { @r = &$f; } elsif (defined wantarray) { $r = &$f; } else { &$f; } warn "exitting $s\n"; wantarray ? @r : $r; } } } } { package T; $r = "r"; sub f { print $_[0].$r.n(); } sub n { @l = l(); 2, chr(@l); } sub l { -5..4; } } sub g { T::f($_[0]."a"); }; g("b");

(Pity overloading "&{}" can not catch named subroutine calls, as that would have been a very elegant solution.)

Update: Note that these codes get much shorter if you only want to trace subroutine entry, not exit, as you don't have to mess with the contexts. You might only want to trace calls that come from a different package. That should be possible with caller.

Replies are listed 'Best First'.
Re^2: Package level scope callbacks.
by BrowserUk (Patriarch) on Aug 01, 2004 at 14:52 UTC

    Thanks for some good ideas and sample code.

    Overloading "&{}" really would be elegant.

    Maybe someone should bring that up on the p6 list in the hope that it can be done over there.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon

      Overloading "&{}" really would be elegant.

      Maybe someone should bring that up on the p6 list in the hope that it can be done over there.

      Thinking about it again, I'd think no. When you call a sub with f(), you can certainly not overload it as it's dereferencing a glob (like &{*f}()), not a reference, and you can not bless globs the way you can do it with references.

        Hmmm, maybe.

        Will P6 have globs? Will P6 allow overloading of $obj.method( ... ) or $anonRef.( ... ). What, if anything will  use overload "&{}" do or mean?

        Interesting possibilities portend.


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "Think for yourself!" - Abigail
        "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://379080]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others contemplating the Monastery: (6)
As of 2024-04-16 22:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found