Определение имени подпрограммы для ссылки на Perl-код
Как определить имя подпрограммы для ссылки на 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
}
Ответы
Ответ 1
Почему бы не спросить, что видит компилятор? (Он будет возвращать __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";
}
Ответ 2
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
Ответ 3
Расширяясь по идее Яна Хартунга (и отказываясь от моего собственного), вы можете получить полное имя и информацию о трассировке независимо от того, что это такое или откуда оно взялось:
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
Я не уверен в вызове имени функции извне, но вы можете получить ее из подпрограммы через caller
:
sub Foo {print "foo!\n";return (caller(0))[3];}
$function_name=Foo();
print "Called $function_name\n";
Это имеет следующий результат:
foo!
Called main::Foo
Конечно, вы можете вернуть имя функции как один из элементов, возвращаемых подпрограммой. Таким образом, вы можете захватить его и иметь возможность отображать его (или использовать его в другой логике и т.д.).