foreach my $var (@lista) — $var é uma referência?
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?
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
}