¿Cómo puedo localizar las variables de Perl en un marco de pila diferente?
Pregunta
Tengo un código generado automáticamente que efectivamente escribe lo siguiente en un montón de lugares diferentes en algún código:
no warnings 'uninitialized';
local %ENV = %ENV;
local $/ = $/;
local @INC = @INC;
local %INC = %INC;
local Tengo un código generado automáticamente que efectivamente escribe lo siguiente en un montón de lugares diferentes en algún código:
<*>
Cuando se genera automáticamente el código, algunos argumentan que no es estrictamente necesario que el código sea `` hermoso '', pero me gustaría llevarlo a una subrutina. Sin embargo, eso localizaría esas variables en esa subrutina. ¿Hay alguna manera 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.
= Tengo un código generado automáticamente que efectivamente escribe lo siguiente en un montón de lugares diferentes en algún código:
<*>
Cuando se genera automáticamente el código, algunos argumentan que no es estrictamente necesario que el código sea `` hermoso '', pero me gustaría llevarlo a una subrutina. Sin embargo, eso localizaría esas variables en esa subrutina. ¿Hay alguna manera 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.
;
local $| = $|;
local %SIG = %SIG;
use warnings 'uninitialized';
Cuando se genera automáticamente el código, algunos argumentan que no es estrictamente necesario que el código sea `` hermoso '', pero me gustaría llevarlo a una subrutina. Sin embargo, eso localizaría esas variables en esa subrutina. ¿Hay alguna manera 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.
Solución
¿Quizás pueda organizar el código que usa esos locales para ser generado como cierre? Entonces podrías
sub run_with_env {
my ($sub, @args) = @_;
no warnings 'uninitialized';
local %ENV = %ENV;
local $/ = $/;
local @INC = @INC;
local %INC = %INC;
local ¿Quizás pueda organizar el código que usa esos locales para ser generado como cierre? Entonces podrías
<*> = ¿Quizás pueda organizar el código que usa esos locales para ser generado como cierre? Entonces podrías
<*>;
local $| = $|;
local %SIG = %SIG;
use warnings 'uninitialized';
$sub->(@args);
}
run_with_env(sub {
# do stuff here
});
run_with_env(sub {
# do different stuff here
});
Otros consejos
No estoy seguro de por qué QuantumPete está siendo rechazado, parece estar en lo cierto en este caso. No puede decirle a local
que inicialice variables en el bloque de llamada. Su funcionalidad es especial, y la inicialización / desmontaje que hace solo funciona en el bloque donde se ejecutó.
Hay algunos módulos experimentales como Sub :: Uplevel y Devel :: RunBlock que le permiten intentar " tonto " caller ()
para subrutinas o hacer un 'retorno de salto largo' de valores a marcos de pila más altos (respectivamente), pero ninguno de estos hace nada para afectar la forma en que local
trata las variables ( Lo intenté. :)
Entonces, por ahora, parece que tendrá que vivir con las declaraciones locales en el ámbito donde las necesita.
No estoy muy familiarizado con Perl, así que perdóname si es posible. Pero normalmente, las variables locales a un marco de pila solo están disponibles dentro de ese marco de pila. No puede acceder a ellos desde uno superior o inferior (a menos que haga una aritmética de puntero hacky pero nunca se garantiza que tenga éxito). Desafortunadamente, los grandes bloques de declaraciones de variables son algo con lo que tendrá que convivir.
QuantumPete
perldoc perlguts 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 a Alias.pm lo suficientemente cerca como para ver lo fácil que podría ser.
En TCL puede usar uplevel . En cuanto a Perl, no lo sé.
Perl tiene Sub :: Uplevel