Search code examples
perlreference

How can I obtain the name of a perl sub from a ref to the sub?


My perl code contains many objects like $wprAtnA and $wprAtnB below, where a subroutine is specified with some set of arguments. Other code, given a "wprAtn," applies the "wprAtn" to some object. That is, the specified sub is invoked.

Once a "wprAtn" has been defined, it would be convenient to be able to review it, to look at what it consists of, including which sub is has been specified. But as we see below, my Dumper command does not give us that information. Nor does print.

Given a ref to a subroutine, is there a way recover its name or at least its source code, so that the person using the code, the person debugging it, can identify the sub from the "wprAtn"?

#!/usr/bin/env perl 
use strict; use warnings;
use feature 'say';
use Data::Dumper qw(Dumper); $Data::Dumper::Sortkeys = 1;

sub dog
{
    say 'we are in ',[caller(0)]->[3],;
    return 1;
}

sub feline
{
    die;
}

my$wprAtnA=
{
    code=>\&dog,
    arg =>
    {
        x=>5,
    }
};

my$wprAtnB=
{
    code=>\&feline,
    arg =>
    {
        verbose=>0,
        text=>'why?',
    }
};

say $wprAtnA->{code};
print Dumper $wprAtnA;
say $wprAtnB->{code};
print Dumper $wprAtnB;

and here I run it

> perl d.pl
CODE(0x7f96dc80e948)
$VAR1 = {
          'arg' => {
                     'x' => 5
                   },
          'code' => sub { "DUMMY" }
        };
CODE(0x7f96db853a80)
$VAR1 = {
          'arg' => {
                     'text' => 'why?',
                     'verbose' => 0
                   },
          'code' => sub { "DUMMY" }
        };

Addition Here is code based on @ikegami's answer

#!/usr/bin/env perl 
use strict; use warnings;
use feature 'say';

sub dog()
{
    say 'we are in ',[caller(0)]->[3],;
    return 1;
}
use Sub::Util qw( subname );
say subname(\&dog);

my$wprAtnA=
{
    code=>\&dog,
    arg =>
    {
        x=>5,
    }
};
say subname($wprAtnA->{code});


Solution

  • Sub::Util's subname and Sub::Identify's sub_fullname provide the fully-qualified name. (Sub::Identify also provides other related subs.)

    Devel::Peek's Dump will also reveal the name and the stash (package) of a referenced sub (among other things).


    On a related note, Sub::Name's subname and Sub::Util's set_subname will set the name of a sub. This is useful for giving anon subs (sub { }) names for stack traces (e.g. from Carp subs) and for the subs mentioned above.