Определение имени подпрограммы ссылки на код Perl - PullRequest
19 голосов
/ 14 сентября 2011

Как определить имя подпрограммы для ссылки на код Perl?Я также хотел бы различать именованные и анонимные подпрограммы.

Благодаря этому вопросу Я знаю, как распечатать код, но я все еще не знаю, как получить имя.

Например, я хотел бы получить '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 ]

21 голосов
/ 14 сентября 2011

Почему бы не спросить, что видит компилятор?(Возвращается __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";
}
8 голосов
/ 06 июня 2014

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
7 голосов
/ 14 сентября 2011

Расширяя идею Яна Хартунга (и отказываясь от моей), вы можете получить полностью определенное имя и некоторую информацию о трассировке, независимо от того, что это такое и откуда оно взято:

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;
}
4 голосов
/ 14 сентября 2011

Я не уверен в вызове имени функции извне, но вы можете получить его из подпрограммы через функцию caller:

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

Это имеет следующий вывод:

foo!
Called main::Foo

Конечно, вы можете вернуть имя функции в качестве одного из элементов, которые возвращает подпрограмма. Таким образом, вы можете захватить его и иметь возможность отображать его (или использовать в другой логике и т. Д.).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...