2010-12-09 9 views
6

Me gustaría obtener dinámicamente una lista de nombres de funciones (como cadenas) o referencias de funciones de cualquier módulo Perl arbitrario disponible en mi sistema. Esto incluiría módulos que pueden tener o no tener, por ejemplo, una matriz global @EXPORT_OK en su espacio de nombres. ¿Es posible tal hazaña? ¿Cómo puede uno sacarlo si es así?¿Puedo obtener dinámicamente una lista de funciones o nombres de funciones de cualquier módulo Perl?

Editar: De la lectura de perlmod, veo que %Some::Module:: sirve como una tabla de símbolos para Some::Module. ¿Es este el lugar correcto para mirar? Si es así, ¿cómo puedo reducir la tabla a solo los nombres de las funciones en Some::Module?

Respuesta

7

Estás en el buen camino. Para Wittle abajo de la tabla de símbolos completo a sólo los submarinos, algo así como esto se puede hacer (Sombrero de punta "Mastering Perl", capítulo 8, para la versión del paquete principal de este):

use strict; # need to turn off refs when needed 
package X; 

sub x {1;}; 
sub y {1;}; 
our $y = 1; 
our $z = 2; 

package main; 

foreach my $entry (keys %X::) { 
    no strict 'refs'; 
    if (defined &{"X::$entry"}) { 
     print "sub $entry is defined\n" ; 
    } 
} 

# OUTPUT 
sub y is defined 
sub x is defined 
+0

aseado. Creo que me estaba acercando a esto al estudiar la presentación de CPAN, 'Symbol :: Table', pero sus formas están un poco avanzadas para mí. –

+0

Esto fallará si se pega en un archivo con 'use strict' en la parte superior. Para evitar sorpresas, y para dejar en claro que esta es una técnica avanzada, agregue 'no strict 'refs'' before' if (defined & {"X :: $ entry"}) {' – Narveson

+0

@Narveson, eso no trabajo, y tampoco es tan grave. Los escalares X-package solo necesitan tener 'nuestro' lanzado delante de ellos. –

7

Usted puede encontrar este sencillo script útil:

#!/usr/bin/env perl 
use strict; 
use warnings;  
use Data::Dumper; 

# dump of object's symbol table: 
foreach my $className (@ARGV) 
{ 
    print "symbols in $className:"; 

    eval "require $className"; 
    die "Can't load $className: [email protected]" if [email protected]; 

    no strict 'refs'; 
    print Dumper(\%{"main::${className}::"}); 
} 

Pero, si está haciendo esto en el código de producción, que haría uso de Package::Stash lugar:

my @subs_in_foo = Package::Stash->new('Foo')->list_all_symbols('CODE'); 
+0

Me alegra decir 'use strict' y la parte superior y' no strict 'refs'' donde sea necesario. – Narveson

0

estoy usando Perl 5.20 . Esto funciona en mi máquina:

use strict; 

package foo; 
    our $some_var; 
    sub func1 { return 'func1'} 
    sub func2 { return 'func2'} 

package main; 
    sub callable { 
     my ($x) = @_; 
     return defined(&$x); 
    } 

    while (my ($k, $v) = each(%foo::)) { 
     if (callable($v)) { 
     print("$k\n"); 
     } 
    } 

    # output: 
    # func1 
    # func2 
Cuestiones relacionadas