Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
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 taking refuge in the Monastery: (5)
As of 2024-04-20 14:46 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found