2008-10-14 10 views
24

que tienen algún código generado automáticamente que escribe de manera efectiva el siguiente en un montón de lugares diferentes en algún código:¿Cómo puedo localizar las variables de Perl en un marco de pila diferente?

no warnings 'uninitialized'; 
local %ENV = %ENV; 
local $/ = $/; 
local @INC = @INC; 
local %INC = %INC; 
local $_ = $_; 
local $| = $|; 
local %SIG = %SIG; 
use warnings 'uninitialized'; 

Cuando el código de generación de automóviles, algunos argumentan que no es estrictamente necesario que el código sea " hermoso ", pero me gustaría sacar eso en una subrutina. Sin embargo, eso localizaría esas variables en esa subrutina. ¿Hay alguna forma de localizar esas variables en el marco de la pila de llamadas?

Actualización: En una línea similar, sería bueno poder ejecutar eval en un marco de pila más alto. Creo que Python ya tiene esto. Sería bueno si Perl también lo hiciera.

+0

¿Estás seguro de que viste esto en Python? El 'nivel de desarrollo' de Tcl viene a la mente. Pero la respuesta de hexten es mucho mejor de todos modos. – cfi

Respuesta

30

¿Tal vez pueda hacer que el código que utiliza esos locales se genere como cierre? Posteriormente, se podría perlguts

sub run_with_env { 
    my ($sub, @args) = @_; 
    no warnings 'uninitialized'; 
    local %ENV = %ENV; 
    local $/ = $/; 
    local @INC = @INC; 
    local %INC = %INC; 
    local $_ = $_; 
    local $| = $|; 
    local %SIG = %SIG; 
    use warnings 'uninitialized'; 
    $sub->(@args); 
} 

run_with_env(sub { 
    # do stuff here 
}); 

run_with_env(sub { 
    # do different stuff here 
}); 
+2

D'oh! Eso es vergonzosamente obvio en retrospectiva :) Como estoy auto generando código, esto es trivial. – Ovid

+0

¡Es una idea ingeniosa, invertir el problema de esa manera! –

+0

Parece que realmente quieres localizar% main ::. Me pregunto si hay una manera de hacer eso. –

3

No estoy muy familiarizado con Perl, así que perdónenme si es posible. Pero normalmente, las variables locales a un marco de pila solo están disponibles dentro de ese marco de pila. No puedes acceder a ellos desde uno más alto o más bajo (a menos que hagas alguna aritmética de puntero hacky pero nunca se garantiza que tenga éxito). Los grandes bloques de declaraciones de variables lamentablemente son algo con lo que tendrás que vivir.

QuantumPete

+1

Estas variables son variables globales incorporadas. No tienen la sobrecarga cognitiva habitual de los globales ya que son bien conocidos y definidos. Desafortunadamente, todavía tienen un efecto global (como lo hacen las variables globales) y la localización restringe los cambios al alcance actual. – Ovid

+2

Además, local no tiene el comportamiento que estás pensando, no exactamente. local le permite acceder a la variable que está localizada a partir de entonces, modificarla, actualizarla, cambiarla y dejarla continuar en esa pila de llamadas como su valor nuevo/modificado hasta que abandone el cierre en el que se localizó. –

1

En TCL puede utilizar uplevel. En cuanto a Perl, no sé.

+3

Tengo que preguntarme ¿Por qué demonios hay una entrada de Wikipedia para una palabra clave TCL?¿Debería agregar uno para desempaquetar ahora? :) – Ovid

+0

Algo como [Sub :: Uplevel] (http://search.cpan.org/perldoc?Sub::Uplevel)? ¿Es eso para lo que es? – bart

+0

No creo que Sub :: Uplevel me ayude en absoluto, me temo que "llamador" no es un espacio de nombres. –

6

No estoy seguro de por qué QuantumPete está siendo downvoted, parece estar en lo cierto en este caso. No puede indicar local para inicializar variables en el bloque de llamadas. Su funcionalidad es especial, y la inicialización/desmontaje solo funciona en el bloque donde se ejecutó.

Hay algunos módulos experimentales como Sub::Uplevel y Devel::RunBlock que le permiten tratar de "engañar" a caller() de subrutinas o hacer un 'retorno de salto de longitud' de los valores a los marcos de pila superiores (respectivamente), pero ninguno de ellos hace nada para afectar cómo local trata las variables (lo intenté :)

Así que, por ahora, parece que tendrá que vivir con las declaraciones locales en el ámbito donde las necesita.

3

perldoc dice:

The "Alias" module implements localization of the basic types within 
    the caller's scope. People who are interested in how to localize 
    things in the containing scope should take a look there too. 

Fwiw. No he mirado lo suficiente a Alias.pm para ver qué fácil podría ser esto.

Cuestiones relacionadas