So cosa my
c'è in Perl. Definisce una variabile che esiste solo nell'ambito del blocco in cui è definita. Cosa fa our
?
In cosa our
differisce da my
?
So cosa my
c'è in Perl. Definisce una variabile che esiste solo nell'ambito del blocco in cui è definita. Cosa fa our
?
In cosa our
differisce da my
?
Risposte:
Grande domanda: in che cosa our
differisce my
e cosa fa our
?
In sintesi:
Disponibile da Perl 5, my
è un modo per dichiarare variabili non-pacchetto, che sono:
$package_name::variable
.D'altra parte, le our
variabili sono variabili di pacchetto e quindi automaticamente:
$package_name::variable
.La dichiarazione di una variabile con our
consente di prevedere le variabili in modo da utilizzarle use strict
senza ottenere avvisi di battitura o errori di compilazione. Da Perl 5.6, ha sostituito il obsoleto use vars
, che era solo nell'ambito dei file e non come ambito lessicale our
.
Ad esempio, il nome formale e qualificato per la variabile $x
inside package main
è $main::x
. La dichiarazione our $x
consente di utilizzare la $x
variabile bare senza penalità (ovvero, senza un errore risultante), nell'ambito della dichiarazione, quando lo script utilizza use strict
o use strict "vars"
. L'ambito potrebbe essere uno o due o più pacchetti o un piccolo blocco.
local
non crea variabili. Essa non riguarda my
e our
a tutti. local
esegue temporaneamente il backup del valore della variabile e cancella il valore corrente.
our
le variabili non sono variabili del pacchetto. Non sono di portata globale, ma variabili di portata lessicale proprio come le my
variabili. Si può vedere che nel seguente programma: package Foo; our $x = 123; package Bar; say $x;
. Se si desidera "dichiarare" una variabile di pacchetto, è necessario utilizzare use vars qw( $x );
. our $x;
dichiara una variabile con ambito lessicale che è aliasata della variabile con lo stesso nome nel pacchetto in cui è our
stata compilata.
I collegamenti PerlMonks e PerlDoc di Cartman e Olafur sono un ottimo riferimento - di seguito è la mia crepa in un riassunto:
my
le variabili hanno un ambito lessicale all'interno di un singolo blocco definito dallo {}
stesso file o all'interno di esso se non in {}
s. Non sono accessibili da pacchetti / subroutine definiti al di fuori dello stesso ambito / blocco lessicale.
our
le variabili sono incluse in un pacchetto / file e sono accessibili da qualsiasi codice che use
o require
quel pacchetto / file - i conflitti di nomi vengono risolti tra i pacchetti anteponendo lo spazio dei nomi appropriato.
Giusto per concludere, le local
variabili hanno un ambito "dinamico", differendo dalle my
variabili in quanto sono accessibili anche dalle subroutine chiamate all'interno dello stesso blocco.
my
variabili hanno un ambito lessicale [...] all'interno dello stesso file se non in {}
s". Mi è stato utile, grazie.
Un esempio:
use strict;
for (1 .. 2){
# Both variables are lexically scoped to the block.
our ($o); # Belongs to 'main' package.
my ($m); # Does not belong to a package.
# The variables differ with respect to newness.
$o ++;
$m ++;
print __PACKAGE__, " >> o=$o m=$m\n"; # $m is always 1.
# The package has changed, but we still have direct,
# unqualified access to both variables, because the
# lexical scope has not changed.
package Fubb;
print __PACKAGE__, " >> o=$o m=$m\n";
}
# The our() and my() variables differ with respect to privacy.
# We can still access the variable declared with our(), provided
# that we fully qualify its name, but the variable declared
# with my() is unavailable.
print __PACKAGE__, " >> main::o=$main::o\n"; # 2
print __PACKAGE__, " >> main::m=$main::m\n"; # Undefined.
# Attempts to access the variables directly won't compile.
# print __PACKAGE__, " >> o=$o\n";
# print __PACKAGE__, " >> m=$m\n";
# Variables declared with use vars() are like those declared
# with our(): belong to a package; not private; and not new.
# However, their scoping is package-based rather than lexical.
for (1 .. 9){
use vars qw($uv);
$uv ++;
}
# Even though we are outside the lexical scope where the
# use vars() variable was declared, we have direct access
# because the package has not changed.
print __PACKAGE__, " >> uv=$uv\n";
# And we can access it from another package.
package Bubb;
print __PACKAGE__, " >> main::uv=$main::uv\n";
Far fronte a Scoping è una buona panoramica delle regole di scoping Perl. È abbastanza vecchio che our
non è discusso nel corpo del testo. È affrontato nella sezione Note alla fine.
L'articolo parla delle variabili del pacchetto e dell'ambito dinamico e di come ciò differisca dalle variabili lessicali e dall'ambito lessicale.
my
è usato per le variabili locali, mentre our
è usato per le variabili globali.
Maggiori informazioni su Scoping variabile in Perl: le basi .
${^Potato}
è globale. Si riferisce alla stessa variabile indipendentemente da dove la si utilizza.
Ho mai incontrato alcune insidie sulle dichiarazioni lessicali in Perl che mi hanno incasinato, che sono anche legate a questa domanda, quindi aggiungo solo il mio sommario qui:
1. Definizione o dichiarazione?
local $var = 42;
print "var: $var\n";
L'output è var: 42
. Tuttavia non abbiamo potuto dire se si local $var = 42;
tratta di una definizione o dichiarazione. Ma che dire di questo:
use strict;
use warnings;
local $var = 42;
print "var: $var\n";
Il secondo programma genererà un errore:
Global symbol "$var" requires explicit package name.
$var
non è definito, il che significa che local $var;
è solo una dichiarazione! Prima di utilizzare local
per dichiarare una variabile, assicurarsi che sia stata precedentemente definita come variabile globale.
Ma perché questo non fallirà?
use strict;
use warnings;
local $a = 42;
print "var: $a\n";
L'uscita è: var: 42
.
Questo perché $a
, oltre che $b
, è una variabile globale predefinita in Perl. Ricorda la funzione di ordinamento ?
2. Lessico o globale?
Ero un programmatore C prima di iniziare a usare Perl, quindi il concetto di variabili lessicali e globali mi sembra semplice: corrisponde solo alle variabili auto ed esterne in C. Ma ci sono piccole differenze:
In C, una variabile esterna è una variabile definita all'esterno di qualsiasi blocco funzione. D'altra parte, una variabile automatica è una variabile definita all'interno di un blocco funzione. Come questo:
int global;
int main(void) {
int local;
}
Mentre in Perl, le cose sono sottili:
sub main {
$var = 42;
}
&main;
print "var: $var\n";
L'output è var: 42
. $var
è una variabile globale anche se definita in un blocco funzione! In realtà in Perl, ogni variabile è dichiarata come globale per impostazione predefinita.
La lezione è quella di aggiungere sempre use strict; use warnings;
all'inizio di un programma Perl, che costringerà il programmatore a dichiarare esplicitamente la variabile lessicale, in modo da non incasinarci per alcuni errori dati per scontati.
Il perldoc ha una buona definizione della nostra.
A differenza di my, che alloca sia l'archiviazione per una variabile che associa un nome semplice a tale archiviazione da utilizzare nell'ambito corrente, i nostri associati associano un nome semplice a una variabile pacchetto nel pacchetto corrente, da utilizzare nell'ambito corrente. In altre parole, il nostro ha le stesse regole di scoping del mio, ma non crea necessariamente una variabile.
Questo è solo in qualche modo correlato alla domanda, ma ho appena scoperto un (per me) oscuro bit di sintassi perl che puoi usare con le "nostre" variabili (pacchetto) che non puoi usare con "mio" (locale) variabili.
#!/usr/bin/perl
our $foo = "BAR";
print $foo . "\n";
${"foo"} = "BAZ";
print $foo . "\n";
Produzione:
BAR
BAZ
Questo non funzionerà se cambi "da" a "mio".
perl -e "my $foo = 'bar'; print $foo; ${foo} = 'baz'; pr int $foo"
output: barbaz
perl -e "my $foo = 'bar'; print $foo; ${"foo"} = 'baz'; print $foo"
output: barbaz
perl -e "my $foo = 'bar'; print $foo; ${\"foo\"} = 'baz'; print $foo"
output: barbar
Nel mio test ero caduto nella stessa trappola. $ {foo} è uguale a $ foo, le parentesi sono utili durante l'interpolazione. $ {"foo"} è in realtà uno sguardo a $ main :: {} che è la tabella dei simboli principale, in quanto tale contiene solo variabili con ambito pacchetto.
perl -e "package test; our $foo = 'bar'; print $foo; ${\"foo\"} = 'baz'; print $foo"
opera sensibile al pacchetto , poiché in questo contesto $ {"foo"} è ora uguale a $ {"test :: foo"}. Of Symbol Tables and Globs contiene alcune informazioni, così come il libro di programmazione Advanced Perl. Ci scusiamo per il mio precedente errore.
print "package is: " . __PACKAGE__ . "\n";
our $test = 1;
print "trying to print global var from main package: $test\n";
package Changed;
{
my $test = 10;
my $test1 = 11;
print "trying to print local vars from a closed block: $test, $test1\n";
}
&Check_global;
sub Check_global {
print "trying to print global var from a function: $test\n";
}
print "package is: " . __PACKAGE__ . "\n";
print "trying to print global var outside the func and from \"Changed\" package: $test\n";
print "trying to print local var outside the block $test1\n";
Emetterà questo:
package is: main
trying to print global var from main package: 1
trying to print local vars from a closed block: 10, 11
trying to print global var from a function: 1
package is: Changed
trying to print global var outside the func and from "Changed" package: 1
trying to print local var outside the block
Nel caso in cui l'utilizzo di "Usa rigoroso" ottenga questo errore durante il tentativo di eseguire lo script:
Global symbol "$test1" requires explicit package name at ./check_global.pl line 24.
Execution of ./check_global.pl aborted due to compilation errors.
Prova a utilizzare il seguente programma:
#!/usr/local/bin/perl
use feature ':5.10';
#use warnings;
package a;
{
my $b = 100;
our $a = 10;
print "$a \n";
print "$b \n";
}
package b;
#my $b = 200;
#our $a = 20 ;
print "in package b value of my b $a::b \n";
print "in package b value of our a $a::a \n";
#!/usr/bin/perl -l
use strict;
# if string below commented out, prints 'lol' , if the string enabled, prints 'eeeeeeeee'
#my $lol = 'eeeeeeeeeee' ;
# no errors or warnings at any case, despite of 'strict'
our $lol = eval {$lol} || 'lol' ;
print $lol;
our
e my
diverso? Come mostra questo esempio?
Pensiamo a cosa sia realmente un interprete: è un pezzo di codice che memorizza i valori in memoria e consente alle istruzioni in un programma che interpreta di accedere a quei valori con i loro nomi, che sono specificati in queste istruzioni. Quindi, il grande compito di un interprete è quello di modellare le regole di come dovremmo usare i nomi in quelle istruzioni per accedere ai valori che l'interprete memorizza.
Incontrando "mio", l'interprete crea una variabile lessicale: un valore denominato a cui l'interprete può accedere solo mentre esegue un blocco e solo dall'interno di quel blocco sintattico. Incontrando "nostro", l'interprete crea un alias lessicale di una variabile di pacchetto: lega un nome, che l'interprete suppone da allora in poi elaborare come nome di una variabile lessicale, fino al termine del blocco, al valore del pacchetto variabile con lo stesso nome.
L'effetto è che puoi quindi far finta di utilizzare una variabile lessicale e bypassare le regole di "uso rigoroso" sulla qualificazione completa delle variabili del pacchetto. Poiché l'interprete crea automaticamente le variabili del pacchetto quando vengono utilizzate per la prima volta, l'effetto collaterale dell'utilizzo di "our" potrebbe anche essere che l'interprete crea anche una variabile del pacchetto. In questo caso, vengono create due cose: una variabile di pacchetto, a cui l'interprete può accedere da qualsiasi luogo, a condizione che sia correttamente designata come richiesto da "use strict" (anteposto con il nome del suo pacchetto e due due punti) e il suo alias lessicale.
fonti: