2011-09-14 8 views
19

¿Cómo se determinaría el nombre de la subrutina de una referencia de código Perl? También me gustaría distinguir entre subrutinas nombradas y anónimas.Determinar el nombre de la subrutina de una referencia de código Perl

Gracias a this question Sé cómo imprimir el código, pero todavía no sé cómo obtener el nombre.

Por ejemplo, me gustaría llegar 'inigo_montoya' entre los siguientes:

#!/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

dejar de decir eso! –

Respuesta

21

Por qué no preguntar, ¿Qué ve el compilador? (Devolvería 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"; 
} 
+0

Muy bonito; esto parece funcionar muy bien! ¡Gracias! – vlee

+0

Me encanta la referencia a Inigo Montoya (¡ja!) –

+1

B no es el compilador, es el introspector. – rurban

4

No estoy seguro acerca de llamar el nombre de la función desde el exterior, pero se puede obtener desde dentro la subrutina a través de la función caller:

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

Esto tiene el resultado siguiente:

foo! 
Called main::Foo 

Por supuesto, puede devolver el nombre de la función como uno de los elementos que devuelve la subrutina. De esta forma, puede capturarlo y tener la opción de mostrarlo (o usarlo en otra lógica, etc.).

+0

Desafortunadamente, hay muchas muchas subrutinas. Creo que podría modificarlos a todos en mi espacio de trabajo. – vlee

6

Ampliando la idea de enero Hartung (y desguace de mi propia), se puede obtener un nombre completo y alguna información de seguimiento para no importa qué es o de donde vino:

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; 
} 
+2

¿Es necesario el control 'STASH'? [AFAICT] (http://en.wiktionary.org/wiki/AFAICT) incluso las subrutinas anónimas tienen un paquete. –

8

Sub::Identify hace exactamente esto, ocultando todo lo desagradable B::svref_2object() materia de usted por lo que no tiene 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 
} 

que da salida:

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