Qual è la differenza tra il mio e il locale in Perl?

Sto vedendo entrambi utilizzati in questo script che sto cercando di eseguire il debug e la letteratura non è chiara. Qualcuno può demistificare questo per me?

Scoping dinamico. È un concetto pulito. Molte persone non lo usano o lo capiscono.

Fondamentalmente penso a come creare e ancorare una variabile a un blocco di {}, ambito AKA.

 my $foo if (true); # $foo lives and dies within the if statement. 

Quindi una my variabile è ciò a cui sei abituato. mentre con lo scope dinamico $ var può essere dichiarato ovunque e utilizzato ovunque. Quindi con il local si sospende fondamentalmente l’uso di quella variabile globale e si usa un “valore locale” per lavorare con esso. Quindi local crea un ambito temporaneo per una variabile temporanea.

 $var = 4; print $var, "\n"; &hello; print $var, "\n"; # subroutines sub hello { local $var = 10; print $var, "\n"; &gogo; # calling subroutine gogo print $var, "\n"; } sub gogo { $var ++; } 

Questo dovrebbe stampare:

 4 10 11 4 

La risposta breve è che contrassegna una variabile come privata in ambito lessicale e che contrassegna una variabile come privata in ambito dinamico.

È più facile capire il my , dal momento che crea una variabile locale nel senso comune. È stata creata una nuova variabile ed è accessibile solo all’interno del blocco lessicale che lo contiene, che di solito è contrassegnato da parentesi graffe. Esistono alcune eccezioni alla regola delle parentesi graffe, ad esempio:

 foreach my $x (@foo) { print "$x\n"; } 

Ma è solo Perl a fare quello che intendi. Normalmente hai qualcosa del genere:

 sub Foo { my $x = shift; print "$x\n"; } 

In tal caso, $x è privato della subroutine e il suo ambito è racchiuso tra parentesi graffe. La cosa da notare, e questo è il contrasto con il local , è che l’ambito di una my variabile è definito rispetto al tuo codice così com’è scritto nel file. È un fenomeno in fase di compilazione.

Per capire il local , devi pensare in termini di stack chiamante del tuo programma mentre è in esecuzione. Quando una variabile è local , viene ridefinita dal punto in cui viene eseguita l’istruzione local per tutto ciò che è sotto lo stack, fino a quando non si torna indietro allo stack al chiamante del blocco che contiene il local .

Questo può essere fonte di confusione all’inizio, quindi considera il seguente esempio.

 sub foo { print "$x\n"; } sub bar { local $x; $x = 2; foo(); } $x = 1; foo(); # prints '1' bar(); # prints '2' because $x was localed in bar foo(); # prints '1' again because local from foo is no longer in effect 

Quando foo viene chiamato la prima volta, vede il valore globale di $x che è 1. Quando viene chiamata la bar viene eseguito local $x , che ridefinisce il $x globale nello stack. Ora quando foo viene chiamato dalla bar , vede il nuovo valore di 2 per $x . Finora non è molto speciale, perché la stessa cosa sarebbe accaduta senza la chiamata al local . La magia è che quando la bar ritorna, si esce dall’ambito dinamico creato da local $x e il precedente $x globale rientra nello scope. Quindi per l’ultima chiamata di foo , $x è 1.

Quasi sempre vorrai usare my , dato che ti dà la variabile locale che stai cercando. Una volta in una luna blu, local è davvero utile per fare cose interessanti.

Citando da Learning Perl :

Ma il locale è stato erroneamente chiamato, o almeno ingannevolmente chiamato. Il nostro amico Chip Salzenberg dice che se mai avesse la possibilità di tornare in una macchina del tempo nel 1986 e dare un consiglio a Larry, avrebbe detto a Larry di chiamare il locale con il nome “salva”. [14] Questo perché il locale in realtà salverà il valore della variabile globale, quindi verrà automaticamente ripristinato sulla variabile globale. (Esatto: queste cosiddette variabili “locali” sono in realtà globali!) Questo meccanismo di salvataggio e ripristino è lo stesso che abbiamo già visto due volte, nella variabile di controllo di un ciclo foreach e nella @ matrice di parametri di subroutine.

Quindi, local salva un valore corrente di una variabile globale e quindi lo imposta su una qualche forma di valore vuoto. Vedrai spesso che è usato per consumare un intero file, piuttosto che tracciare solo una riga:

 my $file_content; { local $/; open IN, "foo.txt"; $file_content = ; } 

Chiamando local $/ imposta il separatore del record di input (il valore che Perl interrompe la lettura di una “riga” su) su un valore vuoto, facendo sì che l’operatore della navicella spaziale legga l’intero file, quindi non colpisce mai il separatore del record di input.

Non posso credere che nessuno sia collegato agli esaustivi trattati di Mark Jason Dominus in materia:

  • Affrontare con Scoping

  • E poi, se vuoi sapere che cosa è buono per il local dopo tutto,
    Sette usi utili del local

http://perldoc.perl.org/perlsub.html#Private-Variables-via-my ()

A differenza delle variabili dinamiche create dall’operatore locale, le variabili lessicali dichiarate con my sono completamente nascoste al mondo esterno, incluse le subroutine chiamate. Questo è vero se è la stessa subroutine chiamata da sé o altrove – ogni chiamata riceve la propria copia.

http://perldoc.perl.org/perlsub.html#Temporary-Values-via-local ()

Un locale modifica le sue variabili elencate come “locali” nel blocco che racchiude, eval, o fa FILE – e in qualsiasi subroutine chiamata da quel blocco. Un locale fornisce solo valori temporanei alle variabili globali (ovvero al pacchetto). Non crea una variabile locale. Questo è noto come ambito dinamico. Lo scope lessicale è fatto con my, che funziona più come le dichiarazioni auto di C.

Non penso che questo sia per nulla chiaro, se non per dire che per “locale al blocco che racchiude”, ciò significa che il valore originale viene ripristinato quando si esce dal blocco.

Beh, Google funziona davvero per te su questo: http://www.perlmonks.org/?node_id=94007

Dal link:

Riepilogo rapido: “mio” crea una nuova variabile, “locale” modifica temporaneamente il valore di una variabile.

cioè, “locale” modifica temporaneamente il valore della variabile , ma solo all’interno dello scopo in cui esiste.

Generalmente uso il mio, è più veloce e non fa niente di strano.

man perlsub :

A differenza delle variabili dinamiche create dall’operatore locale, le variabili lessicali dichiarate con my sono completamente nascoste al mondo esterno, incluse le subroutine chiamate.

Quindi, semplificando eccessivamente, il my rende visibile la tua variabile solo dove è dichiarata. local rende visibile anche nello stack delle chiamate. Solitamente vorrete usare my invece di local .

La tua confusione è comprensibile. Lo scope lessicale è abbastanza facile da capire ma lo scoping dinamico è un concetto insolito. La situazione è peggiorata dal fatto che i nomi my e local siano in qualche modo inaccurati (o almeno non intuitivi) per ragioni storiche.

my dichiara una variabile lessicale – una che è visibile dal punto di dichiarazione fino alla fine del blocco (o file) che lo racchiude. È completamente indipendente da qualsiasi altra variabile con lo stesso nome nel resto del programma. È privato di quel blocco.

local , d’altra parte, dichiara una modifica temporanea al valore di una variabile globale. Il cambiamento termina alla fine del campo di applicazione, ma la variabile – essendo globale – è visibile in qualsiasi punto del programma.

Come regola generale, usa my per dichiarare le tue variabili e local per controllare l’impatto delle modifiche alle variabili built-in di Perl.

Per una descrizione più approfondita vedi l’articolo di Mark Jason Dominus Coping with Scoping .

local è un metodo di localizzazione precedente, a partire dal momento in cui Perl aveva solo scope dinamiche. Lo scope lessicale è molto più naturale per il programmatore e molto più sicuro in molte situazioni. le mie variabili appartengono all’ambito (blocco, pacchetto o file) in cui sono dichiarate.

le variabili locali invece appartengono effettivamente a uno spazio dei nomi globale. Se fai riferimento a una variabile $ x con local, in realtà ti stai riferendo a $ main :: x, che è una variabile globale. Contrariamente a ciò che implica il nome, tutto il locale fa è spingere un nuovo valore su una pila di valori per $ main :: x fino alla fine di questo blocco, momento in cui il vecchio valore verrà ripristinato. Questa è una caratteristica utile di per sé, ma non è un buon modo per avere variabili locali per una serie di motivi (pensa cosa succede quando hai discussioni! E pensa cosa succede quando chiami una routine che vuole veramente usare un globale che hai localizzato!). Tuttavia, era l’unico modo per avere variabili che assomigliavano a variabili locali nei vecchi tempi precedenti a Perl 5. Siamo ancora bloccati con esso.

Le “mie” variabili sono visibili solo nel blocco di codice corrente. Le variabili “locali” sono anche visibili ovunque fossero visibili prima. Ad esempio, se dici “my $ x;” e chiama una funzione secondaria, non può vedere quella variabile $ x. Ma se dici “locale $ /;” (per escludere il valore del separatore di record) quindi si cambia il modo in cui la lettura da file funziona in qualsiasi funzione chiamata.

In pratica, quasi sempre vuoi “mio”, non “locale”.

Guarda il seguente codice e il suo output per capire la differenza.

 our $name = "Abhishek"; sub sub1 { print "\nName = $name\n"; local $name = "Abhijeet"; &sub2; &sub3; } sub sub2 { print "\nName = $name\n"; } sub sub3 { my $name = "Abhinav"; print "\nName = $name\n"; } &sub1; 

L’output è:

 Name = Abhishek Name = Abhijeet Name = Abhinav 

L’esempio di dinomite di usare locale per ridefinire il delimitatore di record è l’unica volta in cui ho corso in un sacco di programmi perl. Vivo in un ambiente perl di nicchia [programmazione di sicurezza], ma nella mia esperienza è un ambito raramente utilizzato.

 &s; sub s() { local $s="5"; &b; print $s; } sub b() { $s++; } 

Lo script precedente stampa 6.

Ma se cambiamo locale al mio verrà stampato 5.

Questa è la differenza. Semplice.

Penso che il modo più semplice per ricordarlo sia in questo modo. MY crea una nuova variabile. LOCAL modifica temporaneamente il valore di una variabile esistente.