2011-09-14 1 views
19

Come si determina il nome di subroutine di un riferimento al codice Perl? Vorrei anche distinguere tra subroutine nominate e anonime.Determinazione del nome di subroutine di un riferimento al codice Perl

Grazie a this question So come stampare il codice, ma ancora non so come ottenere il nome.

Per esempio, mi piacerebbe ottenere 'inigo_montoya' dal seguente:

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

smettere di dire che! –

risposta

21

Perché non chiedere, cosa vede il compilatore? (Restituirebbe su sottotitoli anonimi).

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

Molto bello; questo sembra funzionare alla grande! Grazie! – vlee

+0

Ama il riferimento a Inigo Montoya (ha!) –

+1

B non è il compilatore, è l'introspetore. – rurban

4

io non sono sicuro di chiamare il nome della funzione da fuori, ma è possibile ottenere dal di dentro la subroutine tramite la funzione caller:

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

Questo ha il seguente risultato:

foo! 
Called main::Foo 

Ovviamente, è possibile restituire il nome della funzione come uno degli elementi restituiti dalla subroutine. In questo modo, puoi catturarlo e avere la possibilità di visualizzarlo (o usarlo in un'altra logica, ecc.).

+0

Sfortunatamente ci sono molte molte subroutine. Immagino di poterli modificare tutti nel mio spazio di lavoro. – vlee

6

Ampliando l'idea di Jan Hartung (e rottamazione mio), si potrebbe ottenere un nome completo e alcune informazioni di traccia per non importa quello che è o da dove proviene:

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

È necessario il controllo 'STASH'? [AFAICT] (http://en.wiktionary.org/wiki/AFAICT) anche le subroutine anonime hanno un pacchetto. –

8

Sub::Identify fa esattamente questo, nascondendo tutto quel brutto B::svref_2object() roba da voi in modo da non devi pensarci.

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

quali uscite:

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