Pergunta

Como uso muito $_ quero entender melhor seu uso.$_ é uma variável global para valores implícitos, tanto quanto eu entendi e usei.

Como $_ parece estar definido de qualquer maneira, existem razões para usar variáveis ​​de loop nomeadas em $_ além do mais legibilidade?

Em que casos importa que $_ seja uma variável global?

Então se eu usar

for (@array){
    print $_;
}

ou mesmo

print $_ for @array;

tem o mesmo efeito que

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

Mas funciona da mesma forma?Eu acho que não exatamente, mas quais são as diferenças reais?

Atualizar:

Parece que $_ tem o escopo correto neste exemplo.Não é mais global?Estou 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 corretamente 1234one1234two1234três1234four.

Para $_ global eu teria esperado 1234 4 1234 4 1234 4 1234 4 ..ou estou faltando algo óbvio?

Quando $_ é global então?

Atualizar:

Ok, depois de ler as várias respostas e o perlsyn com mais atenção, cheguei a uma conclusão:

Além da legibilidade, é melhor evitar o uso de $_ porque a localização implícita de $_ deve ser conhecida e levada em consideração, caso contrário, poderá encontrar um comportamento inesperado.

Obrigado pelo esclarecimento desse assunto.

Foi útil?

Solução

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

A questão não é se eles são nomeados ou não.A questão é se elas são "variáveis ​​de pacote" ou "variáveis ​​lexicais".

Veja a muito boa descrição dos 2 sistemas de variáveis ​​usados ​​em Perl "Coping with Scoping":

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

variáveis ​​de pacote são variáveis ​​globais e devem, portanto, ser evitadas por todas as razões usuais (por exemplo.ação à distância).

Evitar variáveis ​​de pacote é uma questão de "operação correta" ou "mais difícil de injetar bugs" ao invés de uma questão de "legibilidade".

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

Em todos os lugares.

A melhor pergunta é:

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

Existem alguns lugares onde o Perl irá local()izar $_ para você, principalmente foreach, grep e map.Todos os outros lugares exigem que você local()ize você mesmo, portanto você estará injetando um bug em potencial quando inevitavelmente se esquecer de fazê-lo.:-)

Outras dicas

O clássico modo de falha de uso $_ (implícita ou explicitamente) como uma variável de loop é

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

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

onde, porque a variável de loop em for/foreach está vinculado ao item da lista real, significa que o while (<F>) substitui @myarray com linhas lidas dos arquivos.

$_ é o mesmo que nomear a variável como no seu segundo exemplo da maneira como ela normalmente é usada.$_ é apenas um nome de variável padrão de atalho para o item atual no loop atual para economizar digitação ao fazer um loop simples e rápido.Costumo usar variáveis ​​nomeadas em vez do padrão.Deixa mais claro o que é e se acontecer de eu precisar fazer um loop aninhado não há conflitos.

Como $_ é uma variável global, você pode obter valores inesperados se tentar usar o valor que tinha em um bloco de código anterior.O novo bloco de código pode fazer parte de um loop ou outra operação que insere seus próprios valores em $_, substituindo o que você esperava que estivesse lá.

O risco de usar $_ é que ele é global (a menos que você o localize com local $_) e, portanto, se alguma função que você chama no seu loop também usa $_, os dois usos podem interferir.

Por razões que não são claras para mim, isso só me incomoda ocasionalmente, mas normalmente localizo $_ se o uso dentro de pacotes.

Não há nada de especial nisso $_ além disso, é o parâmetro padrão para muitas funções.Se você definir explicitamente o escopo lexical do seu $_ com my, perl usará a versão local do $_ em vez do global.Não há nada de estranho nisso, é como qualquer outra variável nomeada.

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

Você deve ficar um pouco confuso com a saída até descobrir que o perl preservará o valor original da variável do loop na saída do loop (veja perlsyn).

Observação ex2 acima.Aqui, o segundo loop está usando o escopo lexical $_ declarado no primeiro loop.Sutil, mas esperado.Novamente, este valor é preservado na saída, então os dois loops não interferir.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top