2011-03-04 13 views
8

Estoy tratando de obtener una representación de texto del nombre de una variable. Por ejemplo, esto sería la función Busco:Obtener el nombre de la variable como una cadena en Perl

$abc = '123'; 
$var_name = &get_var_name($abc); #returns '$abc' 

Quiero esto porque estoy tratando de escribir una función de depuración que emite de forma recursiva los contenidos de una variable pasada, yo quiero que la salida el nombre de la variable de ante mano, así que si llamo a esta función de depuración 100 veces seguidas, no habrá confusión en cuanto a qué variable estoy viendo en la salida.

He oído hablar de Data :: Dumper y no soy fan. Si alguien puede decirme cómo hacerlo si es posible obtener una cadena del nombre de una variable, sería genial.

Gracias!

+4

¿Por qué no utilizar las herramientas de depuración incorporadas de Perl en lugar de reinventar la rueda? – Cfreak

+1

Sospecho que Devel :: StackTrace sería una mejor solución a su problema que buscar nombres de variables. – Quentin

+1

¿Por qué no eres fanático de Data :: Dumper? Si sabemos exactamente cuáles son sus requisitos y por qué Data :: Dumper no los satisface, será más fácil responder a su pregunta. Sin más información, todo lo que puedo hacer es recomendar Data :: Dumper porque es lo que uso para esto. –

Respuesta

-2

"mis" (léxicos) nombres de variables se borran, por lo que no puede obtener sus nombres. Los nombres de las variables del paquete están disponibles a través de la entrada de la tabla de símbolos (*var), como se menciona en otro artículo.

8

Data::Dumper::Simple

use warnings; 
use strict; 
use Data::Dumper::Simple; 

my $abc = '123'; 
my ($var_name) = split /=/, Dumper($abc); 
print $var_name, "\n"; 

__END__ 

$abc 
6

Para ello, es necesario utilizar el módulo PadWalker, que le permite inspeccionar las almohadillas léxicas que almacenan las variables.

use PadWalker qw/peek_my peek_our/; 

sub debug { 
    my $my  = peek_my 1; 
    my $our = peek_our 1; 
    my $caller = caller() . '::'; 
    my $stash = do { 
     no strict 'refs'; 
     \%$caller 
    }; 
    my %lookup; 
    for my $pad ($my, $our) { 
     $lookup{$$pad{$_}} ||= $_ for keys %$pad; 
    } 
    for my $name (keys %$stash) { 
     if (ref \$$stash{$name} eq 'GLOB') { 
      for (['$' => 'SCALAR'], 
       ['@' => 'ARRAY'], 
       ['%' => 'HASH'], 
       ['&' => 'CODE']) { 
       if (my $ref = *{$$stash{$name}}{$$_[1]}) { 
        $lookup{$ref} ||= $$_[0] . $caller . $name 
       } 
      } 
     } 
    } 
    for (@_) { 
     my $name = $lookup{\$_} || 'name not found'; 
     print "$name: $_\n"; 
    } 
} 

y luego se usa:

my $x = 5; 
our $y = 10; 
$main::z = 15; 

debug $x, $y, $main::z; 

que imprime:

$x: 5 
$y: 10 
$main::z: 15 

EDIT:

aquí es la misma funcionalidad, rediseñado un poco:

use PadWalker qw/peek_my peek_our/; 

sub get_name_my { 
    my $pad = peek_my($_[0] + 1); 
    for (keys %$pad) { 
     return $_ if $$pad{$_} == \$_[1] 
    } 
} 
sub get_name_our { 
    my $pad = peek_our($_[0] + 1); 
    for (keys %$pad) { 
     return $_ if $$pad{$_} == \$_[1] 
    } 
} 
sub get_name_stash { 
    my $caller = caller($_[0]) . '::'; 
    my $stash = do { 
     no strict 'refs'; 
     \%$caller 
    }; 
    my %lookup; 
    for my $name (keys %$stash) { 
     if (ref \$$stash{$name} eq 'GLOB') { 
      for (['$' => 'SCALAR'], 
       ['@' => 'ARRAY'], 
       ['%' => 'HASH'], 
       ['&' => 'CODE']) { 
       if (my $ref = *{$$stash{$name}}{$$_[1]}) { 
        $lookup{$ref} ||= $$_[0] . $caller . $name 
       } 
      } 
     } 
    } 
    $lookup{\$_[1]} 
} 
sub get_name { 
    unshift @_, @_ == 2 ? 1 + shift : 1; 
    &get_name_my or 
    &get_name_our or 
    &get_name_stash 
} 

sub debug { 
    for (@_) { 
     my $name = get_name(1, $_) || 'name not found'; 
     print "$name: $_\n"; 
    } 
} 
Cuestiones relacionadas