Pregunta

Estoy viendo a los dos utilizados en este script que estoy tratando de depurar y la literatura simplemente no es clara. ¿Alguien puede desmitificar esto por mí?

¿Fue útil?

Solución

Ámbito dinámico. Es un concepto limpio. Muchas personas no lo usan o no lo entienden.

Básicamente piense en my como crear y anclar una variable en un bloque de {}, A.K.A. alcance.

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

Entonces, una variable my es a lo que estás acostumbrado. mientras que con el alcance dinámico $ var puede declararse en cualquier lugar y usarse en cualquier lugar. Entonces, con local básicamente suspendes el uso de esa variable global, y usas un " valor local " para trabajar con eso. Entonces local crea un alcance temporal para una variable temporal.

$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 ++;
}

Esto debería imprimir:

4
10
11
4

Otros consejos

La respuesta corta es que my marca una variable como privada en un ámbito léxico, y local marca una variable como privada en un ámbito dinámico.

Es más fácil entender my , ya que eso crea una variable local en el sentido habitual. Se crea una nueva variable y solo es accesible dentro del bloque léxico adjunto, que generalmente está marcado con llaves. Hay algunas excepciones a la regla de llaves, como:

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

Pero eso es solo Perl haciendo lo que quieres decir. Normalmente tienes algo como esto:

sub Foo {
   my $x = shift;

   print "$x\n";
}

En ese caso, $ x es privado para la subrutina y su alcance está encerrado entre llaves. Lo que hay que tener en cuenta, y este es el contraste con local , es que el alcance de una variable my se define con respecto a su código tal como está escrito en el archivo. Es un fenómeno en tiempo de compilación.

Para entender local , debe pensar en términos de la pila de llamadas de su programa mientras se ejecuta. Cuando una variable es local , se redefine desde el punto en el que se ejecuta la instrucción local para todo lo que está debajo de eso en la pila, hasta que regrese de nuevo la pila a la persona que llama del bloque que contiene el local .

Esto puede ser confuso al principio, así que considere el siguiente ejemplo.

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

Cuando se llama a foo por primera vez, ve el valor global de $ x que es 1. Cuando se llama a bar y < code> local $ x se ejecuta, que redefine el $ x global en la pila. Ahora, cuando se llama a foo desde bar , ve el nuevo valor de 2 para $ x . Hasta ahora eso no es muy especial, porque lo mismo hubiera pasado sin la llamada a local . La magia es que cuando bar regresa, salimos del ámbito dinámico creado por local $ x y el $ x global anterior vuelve a estar dentro del ámbito. Entonces, para la última llamada de foo , $ x es 1.

Casi siempre querrás usar my , ya que eso te da la variable local que estás buscando. Una vez en una luna azul, local es realmente útil para hacer cosas geniales.

Cita de Learning Perl :

  

Pero local tiene un nombre incorrecto, o al menos un nombre engañoso. Nuestro amigo Chip Salzenberg dice que si alguna vez tiene la oportunidad de regresar en una máquina del tiempo a 1986 y darle un consejo a Larry, le diría a Larry que llame al local por el nombre "guardar". en su lugar. [14] Esto se debe a que local realmente ahorrará el valor de la variable global dada, por lo que luego se restaurará automáticamente a la variable global. (Así es: ¡estas llamadas variables '' locales '' son en realidad globales!) Este mecanismo de salvar y restaurar es el mismo que ya hemos visto dos veces, en la variable de control de un bucle foreach y en el @ _ conjunto de parámetros de subrutina.

Entonces, local guarda el valor actual de una variable global y luego lo configura en alguna forma de valor vacío. A menudo verás que se usa para sorber un archivo completo, en lugar de dirigir solo una línea:

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

Llamar a local $ / establece el separador de registro de entrada (el valor en el que Perl deja de leer una '' línea '') en un valor vacío, lo que hace que el operador de la nave espacial lea todo el archivo, por lo que nunca golpea el separador de registro de entrada.

No puedo creer que nadie se haya vinculado a Mark Jason Dominus & # 8217; tratados exhaustivos al respecto:

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

  

A diferencia de las variables dinámicas creadas por   el operador local, variables léxicas   declarado con mi están totalmente ocultos   del mundo exterior, incluido cualquier   llamadas subrutinas Esto es cierto si   es la misma subrutina llamada desde   en sí mismo o en otro lugar: cada llamada recibe   su propia copia.

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

  

Un local modifica sus variables enumeradas   ser " local " al bloque de cerramiento,   eval, o hacer ARCHIVO - y a cualquier   subrutina llamada desde dentro de ese   bloquear. Un local solo da temporal   valores a global (paquete de significado)   variables No crea un local   variable. Esto se conoce como dinámico.   alcance El alcance léxico se realiza con   mi, que funciona más como el auto de C   declaraciones.

No creo que esto no esté del todo claro, aparte de decir que por "local al bloque que lo encierra", lo que significa es que el valor original se restablece cuando se sale del bloque.

Bueno, Google realmente funciona para usted en este caso: http://www.perlmonks.org/? node_id = 94007

Desde el enlace:

  

Resumen rápido: 'my' crea un nuevo   variable, 'local' modifica temporalmente   el valor de una variable.

     

es decir, 'local' cambia temporalmente el   valor de la variable , pero solo    dentro del alcance en el que existe.

Generalmente usa my, es más rápido y no hace nada raro.

De man perlsub :

A diferencia de las variables dinámicas creadas por el operador local, las variables léxicas declaradas con my están totalmente ocultas del mundo exterior, incluidas las subrutinas llamadas.

Entonces, simplificando demasiado, my hace que su variable sea visible solo donde se declara. local también lo hace visible en la pila de llamadas. Por lo general, querrá usar my en lugar de local .

Tu confusión es comprensible. El alcance léxico es bastante fácil de entender, pero el alcance dinámico es un concepto inusual. La situación empeora debido a que los nombres my y local son algo inexactos (o al menos no intuitivos) por razones históricas.

my declara una variable léxica, una que es visible desde el punto de declaración hasta el final del bloque (o archivo) adjunto. Es completamente independiente de cualquier otra variable con el mismo nombre en el resto del programa. Es privado para ese bloque.

local , por otro lado, declara un cambio temporal en el valor de una variable global. El cambio finaliza al final del alcance, pero la variable, que es global, es visible en cualquier parte del programa.

Como regla general, use my para declarar sus propias variables y local para controlar el impacto de los cambios en las variables integradas de Perl.

Para obtener una descripción más detallada, consulte el artículo de Mark Jason Dominus Enfrentando el alcance .

local es un método de localización más antiguo, desde los tiempos en que Perl solo tenía un alcance dinámico. El alcance léxico es mucho más natural para el programador y mucho más seguro en muchas situaciones. mis variables pertenecen al ámbito (bloque, paquete o archivo) en el que se declaran.

Las

variables locales en realidad pertenecen a un espacio de nombres global. Si se refiere a una variable $ x con local, en realidad se refiere a $ main :: x, que es una variable global. Contrariamente a lo que su nombre implica, todo lo que hace localmente es insertar un nuevo valor en una pila de valores para $ main :: x hasta el final de este bloque, momento en el cual se restablecerá el valor anterior. Esa es una característica útil en sí misma, pero no es una buena manera de tener variables locales por muchas razones (¡piense qué sucede cuando tiene hilos! Y piense qué sucede cuando llama a una rutina que realmente quiere usar un global que te has localizado!). Sin embargo, era la única forma de tener variables que parecían variables locales en los viejos tiempos antes de Perl 5. Todavía estamos atrapados con eso.

" mi " las variables son visibles solo en el bloque de código actual. " local " Las variables también son visibles donde antes eran visibles. Por ejemplo, si dices " my $ x; " y llama a una subfunción, no puede ver esa variable $ x. Pero si dices " local $ /; " (para anular el valor del separador de registros), luego cambia la forma en que la lectura de archivos funciona en cualquier función que llame.

En la práctica, casi siempre quieres "mi", no "local".

Observe el siguiente código y su salida para comprender la diferencia.

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;

La salida es:

Name = Abhishek

Name = Abhijeet

Name = Abhinav

El ejemplo de dinomite de usar local para redefinir el delimitador de registro es la única vez que me he encontrado en mucha programación de Perl. Vivo en un entorno perl de nicho [programación de seguridad], pero en mi experiencia es realmente un alcance poco utilizado.

&s;

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

sub b()
{
    $s++;
}

El script anterior imprime 6.

Pero si cambiamos local a mi, imprimirá 5.

Esta es la diferencia. Simple.

Creo que la forma más fácil de recordarlo es de esta manera. MY crea una nueva variable. LOCAL cambia temporalmente el valor de una variable existente.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top