2013-06-20 14 views
7

mi chiedo su come posso fare in Perl quello che comunemente fanno in Lisp:le variabili dinamiche in perl

(defvar *verbose-level* 0) 
(defun my-function (... &key ((:verbose-level *verbose-level*) *verbose-level*) ...) ...) 

ciò significa che my-function viene eseguito al livello attuale di prolissità, ma posso passare un diverso livello che interesserà tutte le sue chiamate troppo:

(defun f1 (&key ((:verbose-level *verbose-level*) *verbose-level*)) 
    (format t "~S: ~S=~S~%" 'f1 '*verbose-level* *verbose-level*) 
    (f2 :verbose-level 1) 
    (format t "~S: ~S=~S~%" 'f1 '*verbose-level* *verbose-level*) 
    (f2 :verbose-level (1+ *verbose-level*)) 
    (format t "~S: ~S=~S~%" 'f1 '*verbose-level* *verbose-level*)) 
(defun f2 (&key ((:verbose-level *verbose-level*) *verbose-level*)) 
    (format t "~S: ~S=~S~%" 'f2 '*verbose-level* *verbose-level*)) 
[17]> (f1) 
F1: *VERBOSE-LEVEL*=0 
F2: *VERBOSE-LEVEL*=1 
F1: *VERBOSE-LEVEL*=0 
F2: *VERBOSE-LEVEL*=1 
F1: *VERBOSE-LEVEL*=0 
NIL 
[18]> (f1 :verbose-level 4) 
F1: *VERBOSE-LEVEL*=4 
F2: *VERBOSE-LEVEL*=1 
F1: *VERBOSE-LEVEL*=4 
F2: *VERBOSE-LEVEL*=5 
F1: *VERBOSE-LEVEL*=4 

(notare che le associazioni variabili vengono ripristinate in uscita - anche anormale - dalle funzioni).

Come posso fare qualcosa del genere in Perl?

E.g., in misc.pm, ho our $verbose=0;. Come si scrive una funzione che legherà $verbose ad un valore del suo argomento e ne ripristini il valore al ritorno?

risposta

10

Il concetto di perl delle variabili globali di Perl è abbastanza simile alle variabili speciali in CL.

È possibile “ombra” il valore di una variabile globale con local:

our $var = 1; 

func("before"); 

{ 
    # a block creates a new scope 
    local $var = 2; 
    func("inside"); 
} 

func("after"); 

sub func { say "@_: $var" } 

uscita:

before: 1 
inside: 2 
after: 1 

Se local un valore, il nuovo valore è visibile in tutta la portata dinamica , cioè in tutte le funzioni che vengono chiamate. Il vecchio valore viene ripristinato una volta che lo scope lessicale viene lasciato con qualsiasi mezzo (errori, resi, ecc.). Le chiamate tail non estendono l'ambito dinamico, ma contano come exit dell'ambito.

Si noti che le variabili globali hanno un nome completo. Da un pacchetto diverso, si potrebbe fare qualcosa di simile

local $Other::Package::var = 3; 
Other::Package::func("from a package far, far away"); 

Questo è comunemente utilizzato per fornire la configurazione per i pacchetti con un'interfaccia funzionale (non-OO). Esempi importanti sono Carp e Data::Dumper.

+1

È piuttosto divertente vedere le somiglianze tra Perl e CL. A partire dal modello di compilazione (perché * non dovrebbe * codice essere eseguito durante l'analisi?) Su vassoi lessici speciali o lessicali fino a spazi dei nomi separati (CL: variabili, funzioni, etichette, flussi, ...; Perl: scalari, matrici, hash, sottotitoli, IO, ...).Oh, e CLOS/Moose sono ovviamente correlati – amon

3

Se ho capito bene, è necessario sovrascrivere localmente una variabile globale all'interno di una funzione.

package my_package; 
our $verbose = 0; 

sub function { 
    my ($arg1, $arg2) = @_; # getting function arguments. 
    local $verbose = $arg1; 
} 

Sarà ripristinare vecchio stato di $verbose al ritorno.

+0

Grazie. Cosa succede se 'funzione' viene chiamata senza argomenti? Ad esempio, '$ arg1' non è associato. Devo ricorrere a 'local $ verbose = defined $ arg1? $ arg1: $ verbose' o c'è un approccio più carino? – sds

+0

Puoi scrivere 'local $ verbose = $ arg1 se definito $ arg1;'. –

+0

Questo non ha senso. Se '$ arg1' non è definito, quindi' $ verbose' sarà indefinito. Quello che puoi fare è 'local $ verbose = shift; $ verbose = "default" se non definito $ verbose; '(Oppure usa l'operatore definito o di assegnazione:' $ verbose // = "default" '). – TLP

Problemi correlati