Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Getting the name of sub from sub reference

by gri6507 (Deacon)
on Oct 14, 2010 at 16:24 UTC ( [id://865297]=perlquestion: print w/replies, xml ) Need Help??

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

I am trying to write some generic code which will reference some subroutines that may or may not exist in the code itself. I know how to identify if the subroutine exists given a reference to it. But in the cases where the reference is to a sub that does not exist, I want to print that sub's name. Here's what I have tried so far:

use strict; use warnings; my @q = (\&abc, \&def); my $msg; my $param = "hhhhhh"; foreach my $q (@q) { if (defined(&$q)) { $msg .= $q->($param); } else { $msg .= "cannot call $q\n"; } } print $msg; sub abc { my $q = shift; return "hello from ABC($q)\n"; }

This works correctly for the abc() routine which does exist. Moreover, this code correctly identifies that def() routine does not exist. However, when I print that out, all I get is cannot call CODE(0xac1a40).Is there a way for me to instead print out cannot call def?

Thanks as always!

Replies are listed 'Best First'.
Re: Getting the name of sub from sub reference
by BrowserUk (Patriarch) on Oct 14, 2010 at 17:09 UTC

    Why not just let Perl tell you?

    if( !defined &$c ){ eval{ $c->() }; print $@ };; Undefined subroutine &main::test1 called at (eval 19) line 1, <STDIN> +line 14.

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Getting the name of sub from sub reference
by moritz (Cardinal) on Oct 14, 2010 at 16:46 UTC
    If you do use Devel::Peek; Dump $q[1];

    You can see the sub name in the GVGV::GV field, so the data is still there, and an XS module could certainly retrieve it.

    Maybe Sub::Identify does that, but I haven't tried if it works in this case.

    Perl 6 - links to (nearly) everything that is Perl 6.
      I have used the B module to display the glob's name which is what I think Sub::Identify uses:
      use warnings; use strict; use B qw(svref_2object); sub foo { print "I really do exist!\n"; } for my $coderef ( \&foo, \&bar ) { unless ( defined &$coderef ) { printf "could not call %s\n", svref_2object( $coderef )->GV->N +AME; } } # A symbol table entry is created for bar print "$::{ 'foo' }\n$::{ 'bar' }\n";
Re: Getting the name of sub from sub reference
by morgon (Priest) on Oct 14, 2010 at 16:40 UTC
    One hack you could try:

    Define a AUTOLOAD-sub and then call the code-ref that does not exist.

    The call will then end up in the AUTOLOAD-sub where the (fully qualified) name of the sub is then available in the $AUTOLOAD-variable.

    e.g.:

    use strict; use warnings; use vars qw($AUTOLOAD); my @q = (\&abc, \&def); my $msg; my $param = "hhhhhh"; foreach my $q (@q) { if (defined(&$q)) { $msg .= $q->($param); } else { my $name = $q->(); $msg .= "cannot call $name\n"; } } print $msg; sub abc { my $q = shift; return "hello from ABC($q)\n"; } sub AUTOLOAD { return $AUTOLOAD; }
    This will produce "cannot call main::def".

    Getting rid of the package-part is an easy exercise left for the reader.

Re: Getting the name of sub from sub reference
by kcott (Archbishop) on Oct 14, 2010 at 18:26 UTC

    Replace

    $msg .= "cannot call $q\n";

    with

    $msg .= "cannot call @{[eval {&$q}, $@ =~ /^[^&]+(\S+)/]}\n";

    and the output becomes

    hello from ABC(hhhhhh) cannot call &main::def

    You can use

    @{[eval {&$q}, $@ =~ /^[^&]+(\S+)/]}

    in any double-quoted string for whatever reporting purposes you want.

    Thanks to BrowserUk for the eval bit (above).

    -- Ken

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://865297]
Approved by ig
Front-paged by ig
help
Chatterbox?
and the web crawler heard nothing...

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

    No recent polls found