Come posso localizzare le variabili Perl in un frame stack diverso?
Domanda
Ho del codice generato automaticamente che scrive in modo efficace quanto segue in diversi punti di un certo codice:
no warnings 'uninitialized';
local %ENV = %ENV;
local $/ = $/;
local @INC = @INC;
local %INC = %INC;
local Ho del codice generato automaticamente che scrive in modo efficace quanto segue in diversi punti di un certo codice:
<*>
Quando si genera automaticamente il codice, alcuni sostengono che non è strettamente necessario che il codice sia "bello", ma vorrei estrarlo in un sottoprogramma. Tuttavia, ciò localizzerebbe quelle variabili in quella subroutine. C'è un modo per localizzare quelle variabili nel frame dello stack chiamante?
Aggiorna : in modo simile, sarebbe bello poter eseguire eval in un frame stack superiore. Penso che Python abbia già questo. Sarebbe bello se lo facesse anche Perl.
= Ho del codice generato automaticamente che scrive in modo efficace quanto segue in diversi punti di un certo codice:
<*>
Quando si genera automaticamente il codice, alcuni sostengono che non è strettamente necessario che il codice sia "bello", ma vorrei estrarlo in un sottoprogramma. Tuttavia, ciò localizzerebbe quelle variabili in quella subroutine. C'è un modo per localizzare quelle variabili nel frame dello stack chiamante?
Aggiorna : in modo simile, sarebbe bello poter eseguire eval in un frame stack superiore. Penso che Python abbia già questo. Sarebbe bello se lo facesse anche Perl.
;
local $| = $|;
local %SIG = %SIG;
use warnings 'uninitialized';
Quando si genera automaticamente il codice, alcuni sostengono che non è strettamente necessario che il codice sia "bello", ma vorrei estrarlo in un sottoprogramma. Tuttavia, ciò localizzerebbe quelle variabili in quella subroutine. C'è un modo per localizzare quelle variabili nel frame dello stack chiamante?
Aggiorna : in modo simile, sarebbe bello poter eseguire eval in un frame stack superiore. Penso che Python abbia già questo. Sarebbe bello se lo facesse anche Perl.
Soluzione
Forse puoi organizzare che il codice che utilizza quei locali sia generato come chiusura? Quindi potresti
sub run_with_env {
my ($sub, @args) = @_;
no warnings 'uninitialized';
local %ENV = %ENV;
local $/ = $/;
local @INC = @INC;
local %INC = %INC;
local Forse puoi organizzare che il codice che utilizza quei locali sia generato come chiusura? Quindi potresti
<*> = Forse puoi organizzare che il codice che utilizza quei locali sia generato come chiusura? Quindi potresti
<*>;
local $| = $|;
local %SIG = %SIG;
use warnings 'uninitialized';
$sub->(@args);
}
run_with_env(sub {
# do stuff here
});
run_with_env(sub {
# do different stuff here
});
Altri suggerimenti
Non sono sicuro del motivo per cui QuantumPete è sottovalutato, sembra che abbia ragione su questo. Non puoi dire a local
di inizializzare le variabili nel blocco chiamante. La sua funzionalità è speciale e l'inizializzazione / smontaggio funziona solo sul blocco in cui è stato eseguito.
Esistono alcuni moduli sperimentali come Sub :: Uplevel e Devel :: RunBlock che ti consente di provare a " ingannare " caller ()
per le subroutine o effettua un "salto in lungo" dei valori nei frame stack superiori (rispettivamente), ma nessuno di questi fa nulla per influenzare il modo in cui local
tratta le variabili ( Ho provato. :)
Quindi per ora sembra davvero che dovrete convivere con le dichiarazioni locali nell'ambito in cui ne avete bisogno.
Non ho una grande familiarità con Perl, quindi perdonami se è possibile. Ma normalmente, le variabili locali a un frame dello stack sono disponibili solo all'interno di quel frame dello stack. Non è possibile accedervi da uno più alto o più basso (a meno che non si faccia qualche aritmetica puntatore confuso ma che non è mai garantito per avere successo). Purtroppo, grandi blocchi di dichiarazioni variabili sono qualcosa con cui dovrai convivere.
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. Non ho guardato Alias.pm abbastanza da vicino per vedere quanto potrebbe essere facile.
In TCL puoi utilizzare uplevel . Per quanto riguarda Perl, non lo so.
Perl ha Sub :: Uplevel