Pergunta

Então, eu nunca soube que isso e eu quero obter algumas clarifcation sobre ele.Eu sei que se você fizer

foreach (@list){

se você alterar $_ em que o loop vai afetar os dados reais.Mas, eu não sabia que se você fez

foreach my $var1 (@list){

Se você tiver alterado $var1 no loop seria alterar os dados reais.:-/ Então, há uma maneira de fazer um ciclo @lista, mas manter a variável de uma cópia só de leitura, ou de uma cópia que se mudou não irá alterar o valor no @lista?

Foi útil?

Solução

$var é alias para cada item por sua vez.

Ver http://perldoc.perl.org/perlsyn.html#foreach-loops

Se algum elemento da lista for um LValue, você poderá modificá -lo modificando o VAR dentro do loop. Por outro lado, se algum elemento da lista não for um LValue, qualquer tentativa de modificar esse elemento falhará. Em outras palavras, a variável do índice de loop foreach é um alias implícito para cada item da lista em que você está indo.

Outras dicas

A maneira mais fácil é apenas copiá -lo:

foreach my $var1 (@list) {
    my $var1_scratch = $var1;

ou

foreach my $var1 ( map $_, @list ) {

Mas se $ var1 for uma referência, $ var1_scratch será uma referência à mesma coisa. Para ser realmente seguro, você teria que usar algo como Storable :: Dclone para fazer uma cópia profunda:

foreach my $var1 ( @{ Storable::dclone( \@list ) } ) {
}

(não testado). Então você poderá alterar com segurança $ var1. Mas pode ser caro se o @List for uma grandeestrutura de dados.

É um alias, não uma referência. Se você deseja criar seus próprios aliases (fora de para), você pode usar Data :: Alias.

A única diferença entre esses loops:

foreach (@array) { ... }
foreach my $var (@array) { ... }

é o ciclo variável.O aliasing é uma função de foreach, não a variável implícita $_.Note que este é um alias (outro nome para a mesma coisa) e não um referência (um ponteiro para uma coisa).

A simples (e comum) caso, você pode quebrar o aliasing fazendo uma cópia:

foreach my $var (@array) {
    my $copy = $var;
    # do something that changes $copy
}

Isso funciona para o comum dos valores escalares.Para referências (ou objetos), você precisará fazer uma cópia de profundidade usando Armazenáveis ou Clone, o que pode ser caro.Amarrado variáveis são problemáticos, bem como, perlsyn recomenda evitar a situação completamente.

Não sei como forçar a variável a ser por valor em vez de referência na própria declaração foreach. Você pode copiar o valor de $_ no entanto.

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

use Data::Dumper;

my @data = (1, 2, 3, 4);

print "Before:\n", Dumper(\@data), "\n\n\n";

foreach (@data) {
    my $v = $_;
    $v++;
}

print "After:\n", Dumper(\@data), "\n\n\n";

__END__

Faça uma cópia do @list na declaração para:

foreach my $var1 (() = @list) {
  # modify $var without modifying @list here
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top