Determinación del nombre de la subrutina de una referencia de código Perl
reflection reference (4)
¿Cómo se podría determinar el nombre de subrutina de una referencia de código Perl? También me gustaría distinguir entre subrutinas nombradas y anónimas.
Gracias a esta pregunta , sé cómo imprimir el código, pero todavía no sé cómo obtener el nombre.
Por ejemplo, me gustaría obtener ''inigo_montoya'' de lo siguiente:
#!/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
}
¿Por qué no preguntar qué ve el compilador? ( __ANON__
en subs anónimos).
#!/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";
}
Ampliando la idea de Jan Hartung (y desechando la mía), podría obtener un nombre completo y alguna información de rastreo para lo que sea que sea o de dónde provenga:
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;
}
No estoy seguro de llamar el nombre de la función desde el exterior, pero puede obtenerlo desde la subrutina a través de la función de caller
:
sub Foo {print "foo!/n";return (caller(0))[3];}
$function_name=Foo();
print "Called $function_name/n";
Esto tiene la siguiente salida:
foo!
Called main::Foo
Por supuesto, puede devolver el nombre de la función como uno de los elementos que devuelve la subrutina. De esa manera, puede capturarlo y tener la opción de mostrarlo (o usarlo en otra lógica, etc.).
Sub::Identify hace exactamente esto, ocultándote todas esas cosas desagradables de B::svref_2object()
para que no tengas que pensar en ello.
#!/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
}
Qué salidas:
$ ./sub_identify.pl
Sub Name: inigo_montoya
Stash Name: main
Full Name: main::inigo_montoya