Domanda

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

È stato utile?

Soluzione

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

Basicamente pensa a my come a creare e ancorare una variabile a un blocco di {}, A.K.A. ambito di applicazione.

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

Quindi una variabile my è ciò a cui sei abituato. mentre con lo scoping dinamico $ var può essere dichiarato ovunque e usato ovunque. Quindi con local praticamente sospendi l'uso di quella variabile globale e usi un "valore locale" 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

Altri suggerimenti

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

È più facile capire my , dal momento che crea una variabile locale nel solito senso. È stata creata una nuova variabile ed è accessibile solo all'interno del blocco lessicale allegato, che di solito è contrassegnato da parentesi graffe. Ci sono alcune eccezioni alla regola dei parentesi graffe, come ad esempio:

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

Ma è solo Perl che fa quello che vuoi dire. 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 local , è che l'ambito di una variabile my è definito rispetto al tuo codice così come è scritto nel file. È un fenomeno in fase di compilazione.

Per capire 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 al backup dello stack sul chiamante del blocco contenente il local .

Questo all'inizio può essere fonte di confusione, 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 per la prima volta, viene visualizzato il valore globale di $ x che è 1. Quando viene chiamato bar e < code> local $ x , che ridefinisce il $ x globale nello stack. Ora quando foo viene chiamato da bar , viene visualizzato il nuovo valore di 2 per $ x . Finora non è molto speciale, perché la stessa cosa sarebbe successa senza la chiamata a local . La magia è che quando bar ritorna usciamo dall'ambito dinamico creato da local $ x e il precedente $ x torna all'ambito. Quindi, per la chiamata finale di foo , $ x è 1.

Dovrai quasi sempre usare my , poiché 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 local ha un nome errato, o almeno un nome fuorviante. Il nostro amico Chip Salzenberg dice che se mai avesse la possibilità di tornare in una macchina del tempo al 1986 e dare un consiglio a Larry, avrebbe detto a Larry di chiamare localmente con il nome "save". invece. [14] Questo perché locale in realtà salverà il valore della variabile globale data, 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 ora, nella variabile di controllo di un ciclo foreach e nella @ _ array di parametri di subroutine.

Quindi, local salva il valore corrente di una variabile globale e quindi lo imposta su una forma di valore vuoto. Lo vedrai spesso usato per slurpare un intero file, piuttosto che condurre solo una riga:

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

Chiamando local $ / imposta il separatore del record di input (il valore che Perl interrompe la lettura di una "riga") su un valore vuoto, facendo in modo che l'operatore dell'astronave legga l'intero file, quindi non colpisce mai il separatore del record di input.

Non riesco a credere che nessuno abbia legato a Mark Jason Dominus & # 8217; trattati esaustivi in ??materia:

http://perldoc.perl.org/perlsub .html # private-variabili-via-la mia ()

  

A differenza delle variabili dinamiche create da   l'operatore locale, variabili lessicali   dichiarato con il mio sono totalmente nascosti   dal mondo esterno, incluso qualsiasi   chiamato subroutine. Questo è vero se   è la stessa subroutine chiamata da   stesso o altrove: ogni chiamata viene ricevuta   una sua copia.

http://perldoc.perl.org/perlsub .html # temporaneo valori-via-locale ()

  

Un locale modifica le sue variabili elencate   essere "locale" al blocco allegato,   valutare o fare FILE - e per chiunque   subroutine chiamata dall'interno   bloccare. Un locale dà solo temporaneo   valori globali (significato pacchetto)   variabili. Non crea un locale   variabile. Questo è noto come dinamico   scoping. L'ambito lessicale viene eseguito con   mio, che funziona più come l'auto di C.   dichiarazioni.

Non credo che ciò sia per nulla chiaro, se non per dire che per "locale al blocco che lo 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 un nuovo   variabile, "locale" si modifica temporaneamente   il valore di una variabile.

     

cioè, 'local' cambia temporaneamente il file   valore della variabile , ma solo    nell'ambito di applicazione in cui esiste.

Usa generalmente my, è più veloce e non fa nulla di strano.

Da man perlsub :

A differenza delle variabili dinamiche create dall'operatore locale, le variabili lessicali dichiarate con my sono totalmente nascoste dal mondo esterno, comprese eventuali subroutine.

Quindi, semplificando eccessivamente, my rende la tua variabile visibile solo dove è dichiarata. local lo rende visibile anche nello stack di chiamate. In genere vorrai utilizzare my anziché local .

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

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

local , d'altra parte, dichiara una modifica temporanea al valore di una variabile globale. La modifica termina alla fine dell'ambito di applicazione, ma la variabile - essendo globale - è visibile in qualsiasi parte del programma.

Come regola generale, usa my per dichiarare le tue variabili e local per controllare l'impatto delle modifiche alle variabili incorporate di Perl.

Per una descrizione più approfondita consultare l'articolo di Mark Jason Dominus Far fronte allo scoping .

local è un vecchio metodo di localizzazione, dai tempi in cui Perl aveva solo scoping dinamico. L'ambito 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 ti riferisci a una variabile $ x con local, in realtà stai facendo riferimento a $ main :: x, che è una variabile globale. Contrariamente a quanto implica il nome, tutto ciò che fa local è inserire un nuovo valore in una pila di valori per $ main :: x fino alla fine di questo blocco, quando verrà ripristinato il vecchio valore. Questa è una caratteristica utile in sé e per sé, ma non è un buon modo per avere variabili locali per una serie di ragioni (pensa cosa succede quando hai thread! E pensa cosa succede quando chiami una routine che vuole davvero 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.

" mio " le variabili sono visibili solo nel blocco di codice corrente. & Quot; locale " le variabili sono anche visibili ovunque siano state visibili prima. Ad esempio, se dici " my $ x; " e chiama una sotto-funzione, non può vedere quella variabile $ x. Ma se dici " local $ /; " (per annullare il valore del separatore di record), quindi si cambia il modo in cui la lettura dei file funziona in tutte le funzioni chiamate.

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 sull'uso di local per ridefinire il delimitatore dei record è l'unica volta in cui mi sono imbattuto in molta programmazione perl. Vivo in un ambiente di nicchia perl [programmazione della sicurezza], ma è davvero un ambito usato raramente nella mia esperienza.

&s;

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

sub b()
{
    $s++;
}

Lo script precedente stampa 6.

Ma se cambiamo local in my, 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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top