perl reflection reference

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