确定Perl代码引用的子例程名称

时间:2011-09-14 15:37:03

标签: perl reflection reference

如何确定Perl代码引用的子例程名称?我还想区分命名子程序和匿名子程序。

感谢this question我知道如何打印代码,但我仍然不知道如何获取名称。

例如,我想从以下内容中获取'inigo_montoya':

#!/usr/bin/env perl

use strict;
use warnings;

use Data::Dumper;
$Data::Dumper::Deparse = 1;

my $sub_ref = \&inigo_montoya;

print Dumper $sub_ref;



# === subroutines ===

sub inigo_montoya {
  print <<end_quote;
I will go up to the six-fingered man and say, "Hello. My name is Inigo
Montoya. You killed my father. Prepare to die."';
end_quote
}

4 个答案:

答案 0 :(得分:21)

为什么不问,编译器看到了什么? (它会在匿名潜艇上返回__ANON__

#!/usr/bin/perl

use strict;
use warnings;

my $sub_ref = \&inigo_montoya;


use B qw(svref_2object);
my $cv = svref_2object ( $sub_ref );
my $gv = $cv->GV;
print "name: " . $gv->NAME . "\n";


sub inigo_montoya {
    print "...\n";
}

答案 1 :(得分:8)

Sub::Identify正是如此,隐藏了所有令人讨厌的B::svref_2object()内容,因此您无需考虑它。

#!/usr/bin/env perl

use strict;
use warnings;
use feature 'say';

use Sub::Identify ':all';

my $sub_ref = \&inigo_montoya;

say "Sub Name: ",   sub_name($sub_ref);
say "Stash Name: ", stash_name($sub_ref);
say "Full Name: ",  sub_fullname($sub_ref);

# === subroutines ===

sub inigo_montoya {
    print <<'    end_quote';
I will go up to the six-fingered man and say, "Hello. My name is Inigo
Montoya. You killed my father. Prepare to die."';
    end_quote
}

哪个输出:

$ ./sub_identify.pl 
Sub Name: inigo_montoya
Stash Name: main
Full Name: main::inigo_montoya

答案 2 :(得分:7)

扩展Jan Hartung的想法(并自行删除),您可以获得完全限定的名称和一些跟踪信息,无论它是什么或来自何处:

use B qw(svref_2object);

sub sub_name {
    return unless ref( my $r = shift );
    return unless my $cv = svref_2object( $r );
    return unless $cv->isa( 'B::CV' )
              and my $gv = $cv->GV
              ;
    my $name = '';
    if ( my $st = $gv->STASH ) { 
        $name = $st->NAME . '::';
    }
    my $n = $gv->NAME;
    if ( $n ) { 
        $name .= $n;
        if ( $n eq '__ANON__' ) { 
            $name .= ' defined at ' . $gv->FILE . ':' . $gv->LINE;
        }
    }
    return $name;
}

答案 3 :(得分:4)

我不确定从外部调用函数的名称,但您可以通过caller函数从子例程中获取它:

sub Foo {print "foo!\n";return (caller(0))[3];}
$function_name=Foo();
print "Called $function_name\n";

这有以下输出:

foo!
Called main::Foo

当然,您可以将函数名称作为子例程返回的项之一返回。这样,您可以捕获它并可以选择显示它(或在其他逻辑中使用它等)。