¿En qué se diferencia $_ de los argumentos de bucle o de entrada con nombre?

StackOverflow https://stackoverflow.com/questions/5405423

  •  29-10-2019
  •  | 
  •  

Pregunta

Como uso mucho $_, quiero entender mejor su uso.$_ es una variable global para valores implícitos hasta donde yo la entendí y usé.

Como $_ parece estar configurado de todos modos, ¿hay razones para usar variables de bucle con nombre sobre $_? además ¿legibilidad?

¿En qué casos importa que $_ sea una variable global?

Entonces si uso

for (@array){
    print $_;
}

o incluso

print $_ for @array;

tiene el mismo efecto que

for my $var (@array){
    print $var;
}

¿Pero funciona igual?Supongo que no es así exactamente, pero ¿cuáles son las diferencias reales?

Actualizar:

Parece que $_ incluso tiene un alcance correcto en este ejemplo.¿Ya no es global?Estoy usando 5.12.3.

#!/usr/bin/perl
use strict;
use warnings;

my @array = qw/one two three four/;
my @other_array = qw/1 2 3 4/;

for (@array){
    for (@other_array){
        print $_;
    }
    print $_;
}

que imprime correctamente 1234uno1234dos1234tres1234cuatro.

Para $_ global, habría esperado 1234 4 1234 4 1234 4 1234 4 ..¿O me estoy perdiendo algo obvio?

Entonces, ¿cuándo es $_ global?

Actualizar:

Ok, después de haber leído las distintas respuestas y perlsyn más detenidamente, llegué a una conclusión:

Además de la legibilidad, es mejor evitar el uso de $_ porque la localización implícita de $_ debe conocerse y tenerse en cuenta, de lo contrario se podría encontrar un comportamiento inesperado.

Gracias por aclarar ese asunto.

¿Fue útil?

Solución

are there reasons to use named loop variables over $_ besides readability?

El problema no es si se nombran o no.El problema es si son "variables de paquete" o "variables léxicas".

Vea la muy buena descripción de los 2 sistemas de variables usados en Perl "Afrontando el alcance":

http://perl.plover.com/FAQs/Namespaces.html

Las variables de paquete son variables globales y, por lo tanto, deben evitarse por todas las razones habituales (por ejemplo, acción a distancia).

Evitar las variables del paquete es una cuestión de "funcionamiento correcto" o "más difícil de inyectar errores" en lugar de una cuestión de "legibilidad".

In what cases does it matter $_ is a global variable?

En todas partes.

La mejor pregunta es:

In what cases is $_ local()ized for me?

Hay algunos lugares donde Perl local () izará $ _ para usted, principalmente foreach, grep y map.Todos los demás lugares requieren que usted mismo lo localice (), por lo que estará inyectando un error potencial cuando inevitablemente se olvide de hacerlo.:-)

Otros consejos

El modo de falla clásico de usar $_ (implícita o explícitamente) como una variable de ciclo es

for $_ (@myarray) {
  /(\d+)/ or die;
  foo($1);
}

sub foo {
  open(F, "foo_$_[0]") or die;
  while (<F>) {
    ...
  }
}

donde, debido a que la variable de bucle en for / foreach está vinculada al elemento de la lista real, significa que while (<F>) sobrescribe @myarray con líneas leídas de los archivos.

$ _ es lo mismo que nombrar la variable como en su segundo ejemplo con la forma en que se usa normalmente.$ _ es solo un nombre de variable predeterminado de acceso directo para el elemento actual en el ciclo actual para ahorrar al escribir cuando se hace un ciclo rápido y simple.Tiendo a usar variables con nombre en lugar de las predeterminadas.Deja más claro qué es y si tengo que hacer un bucle anidado, no hay conflictos.

Dado que $ _ es una variable global, puede obtener valores inesperados si intenta usar su valor que tenía de un bloque de código anterior.El nuevo bloque de código puede ser parte de un bucle u otra operación que inserta sus propios valores en $ _, sobrescribiendo lo que esperaba que estuviera allí.

El riesgo de usar $ _ es que es global (a menos que lo localice con local $_), por lo que si alguna función a la que llama en su ciclo también usa $ _, los dos usos pueden interferir.

Por razones que no me quedan claras, esto solo me ha mordido ocasionalmente, pero generalmente localizo $ _ si lo uso dentro de paquetes.

No hay nada especial en $_ además es el parámetro predeterminado para muchas funciones.Si explícitamente abarcas léxicamente tu $_ con my, Perl utilizará la versión local de $_ en lugar del global.No hay nada extraño en esto, es como cualquier otra variable con nombre.

sub p { print "[$_]"; } # Prints the global $_
# Compare and contrast
for my $_ (b1..b5) { for my $_ (a1..a5) { p } } print "\n"; # ex1
for my $_ (b1..b5) { for       (a1..a5) { p } } print "\n"; # ex2
for       (b1..b5) { for my $_ (a1..a5) { p } } print "\n"; # ex3
for       (b1..b5) { for       (a1..a5) { p } } print "\n"; # ex4

Debería estar un poco desconcertado por el resultado hasta que descubra que Perl conservará el valor original de la variable del bucle al salir del bucle (consulte Perlsyn).

Nota ex2 arriba.Aquí el segundo bucle utiliza el ámbito léxico $_ declarado en el primer bucle.Sutil, pero esperado.Nuevamente, este valor se conserva al salir, por lo que los dos bucles no interferir.

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