¿Cuál es la diferencia entre mi y nuestro en Perl?

Sé lo que es my en Perl. Define una variable que existe solo en el scope del bloque en el que está definida. ¿Qué hace our ? ¿Cómo se diferencia our de my ?

Gran pregunta: ¿En qué se diferencia our y qué hace our ?

En resumen:

Disponible desde Perl 5, my es una forma de declarar:

  • variables sin paquete, que son
  • privado,
  • nuevo ,
  • variables no globales ,
  • separado de cualquier paquete. De modo que no se puede acceder a la variable en forma de $package_name::variable .

Por otro lado, our variables son:

  • variables del paquete, y por lo tanto automáticamente
  • variables globales ,
  • definitivamente no es privado ,
  • ni son necesariamente nuevos; y ellos
  • se puede acceder fuera del paquete (o ámbito léxico) con el espacio de nombres calificado, como $package_name::variable .

La statement de una variable con our permite predefinir variables para usarlas bajo use strict sin recibir advertencias de error tipográfico o errores de tiempo de comstackción. Desde Perl 5.6, ha reemplazado los use vars obsoletos, que solo tenían un scope de archivo y no tienen un scope léxico como el our .

Por ejemplo, el nombre formal y calificado para la variable $x dentro del package main es $main::x . Declarar our $x permite usar la variable bare $x sin penalización (es decir, sin un error resultante), en el ámbito de la statement, cuando el script usa use strict o use strict "vars" . El scope puede ser uno, dos o más paquetes o un bloque pequeño.

Los enlaces PerlMonks y PerlDoc de cartman y Olafur son una gran referencia; a continuación se muestra mi resumen de un resumen:

my variables tienen un scope léxico dentro de un único bloque definido por {} o dentro del mismo archivo si no está en {} s. No son accesibles desde paquetes / subrutinas definidos fuera del mismo scope / bloque léxico.

our variables tienen un scope dentro de un paquete / archivo y se puede acceder desde cualquier código que use o require que los conflictos de nombre de paquete / archivo se resuelvan entre paquetes anteponiendo el espacio de nombre apropiado.

Para redondearlo, local variables local tienen un scope “dynamic”, que difiere de my variables en que también se puede acceder desde las subrutinas llamadas dentro del mismo bloque.

Un ejemplo:

 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=$om=$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=$om=$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"; 

Hacer frente al scope es una buena descripción de las reglas de scope de Perl. Ya es lo suficientemente viejo como para que no se discuta en el cuerpo del texto. Se trata en la sección de Notas al final.

El artículo habla sobre las variables del paquete y el scope dynamic y cómo eso difiere de las variables léxicas y el scope léxico.

my se usa para variables locales, mientras que nuestro se usa para variables globales. Más lectura sobre el scope variable en Perl: los conceptos básicos .

Es una vieja pregunta, pero alguna vez me encontré con algunas trampas sobre las declaraciones léxicas en Perl que me desordenaron, que también están relacionadas con esta pregunta, así que simplemente agrego mi resumen aquí:

1. definición o statement?

 local $var = 42; print "var: $var\n"; 

La salida es var: 42 . Sin embargo, no podríamos decir si local $var = 42; es una definición o statement. Pero que tal esto:

 use strict; use warnings; local $var = 42; print "var: $var\n"; 

El segundo progtwig lanzará un error:

 Global symbol "$var" requires explicit package name. 

$var no está definido, lo que significa local $var; es solo una statement! Antes de usar local para declarar una variable, asegúrese de que esté definida como una variable global previamente.

Pero, ¿por qué esto no va a fallar?

 use strict; use warnings; local $a = 42; print "var: $a\n"; 

La salida es: var: 42 .

Eso es porque $a , así como $b , es una variable global predefinida en Perl. ¿Recuerdas la función de ordenar ?

2. léxico o global?

Antes de comenzar a utilizar Perl, era un progtwigdor en C, por lo que el concepto de variables léxicas y globales me parece sencillo: solo corresponde a las variables automáticas y externas en C. Pero hay pequeñas diferencias:

En C, una variable externa es una variable definida fuera de cualquier bloque de funciones. Por otro lado, una variable automática es una variable definida dentro de un bloque de funciones. Me gusta esto:

 int global; int main(void) { int local; } 

Mientras que en Perl, las cosas son sutiles:

 sub main { $var = 42; } &main; print "var: $var\n"; 

El resultado es var: 42 , $var es una variable global, ¡incluso está definida en un bloque de funciones! En realidad, en Perl, cualquier variable se declara global por defecto.

La lección es agregar siempre el use strict; use warnings; use strict; use warnings; al comienzo de un progtwig de Perl, que forzará al progtwigdor a declarar explícitamente la variable léxica, de modo que no nos confundamos con algunos errores que se dan por descontados.

El perldoc tiene una buena definición de nuestro.

A diferencia de my, que asigna almacenamiento para una variable y asocia un nombre simple con ese almacenamiento para usar dentro del scope actual, asocia un nombre simple con una variable de paquete en el paquete actual, para usar dentro del scope actual. En otras palabras, nuestro tiene las mismas reglas de scope que yo, pero no necesariamente crea una variable.

Esto solo está relacionado de alguna manera con la pregunta, pero acabo de descubrir un bit de syntax de perl (para mí) que puedes usar con “nuestras” variables (paquete) que no puedes usar con “mi” (local) variables.

 #!/usr/bin/perl our $foo = "BAR"; print $foo . "\n"; ${"foo"} = "BAZ"; print $foo . "\n"; 

Salida:

 BAR BAZ 

Esto no funcionará si cambia ‘nuestro’ a ‘mi’.

 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"; 

Hará esto:

 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 

En caso de que use “use strict” obtendrá este error al intentar ejecutar el script:

 Global symbol "$test1" requires explicit package name at ./check_global.pl line 24. Execution of ./check_global.pl aborted due to comstacktion errors. 

Intente utilizar el siguiente progtwig:

 #!/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; 

Pensemos qué es realmente un intérprete: es una pieza de código que almacena valores en la memoria y permite que las instrucciones de un progtwig que interpreta accedan a esos valores por sus nombres, que se especifican en estas instrucciones. Entonces, el gran trabajo de un intérprete es dar forma a las reglas de cómo debemos usar los nombres en esas instrucciones para acceder a los valores que almacena el intérprete.

Al encontrar “mi”, el intérprete crea una variable léxica: un valor con nombre al que el intérprete solo puede acceder mientras ejecuta un bloque, y solo desde ese bloque sintáctico. Al encontrar “nuestro”, el intérprete crea un alias léxico de una variable de paquete: vincula un nombre, que se supone que el intérprete debe procesar a partir de ese momento como el nombre de una variable léxica, hasta que el bloque finalice, hasta el valor del paquete variable con el mismo nombre.

El efecto es que puede pretender que está usando una variable léxica y omitir las reglas de ‘uso estricto’ en la calificación completa de las variables del paquete. Como el intérprete crea automáticamente variables de paquete cuando se utilizan por primera vez, el efecto secundario de usar “nuestro” también puede ser que el intérprete también crea una variable de paquete. En este caso, se crean dos cosas: una variable de paquete, a la que el intérprete puede acceder desde cualquier lugar, siempre que se designe adecuadamente como solicitado por ‘use strict’ (precedido por el nombre de su paquete y dos dos puntos) y su alias léxico.

Fuentes: