http://www.perlmonks.org?node_id=715785

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

I have a perl script which automates a ton of database administration work. Much of the logic is duplicated between many of the tasks, so I am using subroutine references extensively to plug in the appropriate custom code where necessary. Since these databases exist in a production environment, audit logs are an absolute necessity. It would be nice to have the names of the subroutines (called by reference) present in the log files.

My question is given a subroutine reference, is it possible to determine the original name of the routine so that it may be placed in the log? Since subroutine references may point to anonymous blocks of code, I suspect that it's not.

As a work-around, I've found that it's possible to pass the subroutine names as text strings. When they're passed into a routine, I check whether they're a scalar (string sub name) or subroutine reference with ref(). If they're a text name, it's easy enough to generate the reference with an eval(), and I can stuff the original name away for later reference.

  • Comment on possible to determine the name of a sub from a sub reference?

Replies are listed 'Best First'.
Re: possible to determine the name of a sub from a sub reference?
by ForgotPasswordAgain (Priest) on Oct 07, 2008 at 14:07 UTC
Re: possible to determine the name of a sub from a sub reference?
by Fletch (Bishop) on Oct 07, 2008 at 13:54 UTC

    Maybe CvGV from Devel::Peek?

    DB<5> x "" . Devel::Peek::CvGV( \&foo ) 0 '*main::foo'

    Also, it's not necessary to resort to eval to generate a coderef from a sub name. Presuming you're trying to get around strict, just temporarily disable it for a small block.

    my $coderef = do { no strict 'refs'; \&{ $subname } };

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

      This nailed it -- Thanks!
Re: possible to determine the name of a sub from a sub reference?
by Anonymous Monk on Oct 07, 2008 at 13:55 UTC
Re: possible to determine the name of a sub from a sub reference?
by mr_mischief (Monsignor) on Oct 07, 2008 at 15:46 UTC
    You might make your task easier by moving it to an earlier point in the code. Rather than trying to find out the name of the subroutine that's already assigned, stick the name of it into the log at the same point in the program where the subroutine is selected.

    A dispatch table built around a hash is a quick and easy way to do this in most situations. It gives you a label to match to determine which subroutine to call which can also be logged before the call is made.

    use strict; use warnings; sub one { print "one\n"; } sub two { print "two\n"; } sub tres { print "never selected!\n"; } my %dispatch = ( 'one' => \&one, 'uno' => \&one, 'two' => \&two, 'dos' => \&two, 'default' => sub { print "sorry, $_[0] not found.\n"; }, ); my @do_these = qw( one two uno dos tres ); my $log; open $log, '>>', 'example.log' or die "Cannot write to log: $!\n"; foreach my $do_this ( @do_these ) { if ( exists $dispatch{ $do_this } ) { print $log $do_this . "\n"; $dispatch{ $do_this }->(); } else { print $log "default: $do_this not found\n"; $dispatch{ 'default' }->( $do_this ); } }
Re: possible to determine the name of a sub from a sub reference?
by JavaFan (Canon) on Oct 07, 2008 at 13:55 UTC
    I do not know if this is the information you want, but one of the elements returned by caller(0) includes the (fully qualified) name of the called subroutine. (It'll be package::__ANON__ for a code block).

    And note that if you have the name of a subroutine, you don't need 'eval' to call it.

    my $name_of_sub = "foo"; $name_of_sub->(...arguments...);
    works, provided you turn off strict 'refs' when you call the subroutine.