foreach my $ var(@list) - $ var是一个参考?

时间:2009-06-18 15:15:41

标签: perl foreach perlsyn

所以,我从来不知道这一点,我希望得到一些澄清。我知道你是否

foreach (@list){

如果在该循环中更改$ _,则会影响实际数据。但是,我不知道如果你做了

foreach my $var1 (@list){

如果您在循环中更改了$ var1,它将更改实际数据。 : - /那么,有没有办法循环@list但保持变量是只读副本,或者如果更改的副本不会更改@list中的值?

6 个答案:

答案 0 :(得分:10)

$var依次为每个项目设置别名。

请参阅http://perldoc.perl.org/perlsyn.html#Foreach-Loops

  

如果LIST的任何元素是左值,您可以通过修改循环内的VAR来修改它。   相反,如果LIST的任何元素不是左值,则任何修改该元素的尝试   将失败。换句话说,foreach循环索引变量是每个的隐式别名   您正在循环的列表中的项目。

答案 1 :(得分:9)

最简单的方法就是复制它:

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

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

但是如果$ var1是一个引用,$ var1_scratch将是对同一个东西的引用。 为了非常安全,你必须使用像Storable :: dclone这样的东西来做深层复制:

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

(未测试)。然后你应该能够安全地改变$ var1。但如果这样做可能会很昂贵 @list是一个很大的数据结构。

答案 2 :(得分:4)

这是别名,不是参考。如果您想创建自己的别名(在for之外),可以使用Data::Alias

答案 3 :(得分:2)

这些循环之间的唯一区别是:

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

是循环变量。别名是foreach的函数,而不是隐式变量$_。请注意,这是别名(同一事物的另一个名称),而不是引用(指向事物的指针)。

在简单(和常见)的情况下,您可以通过复制来破坏别名:

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

这适用于普通的标量值。对于参考(或对象),您需要使用StorableClone制作深层副本,这可能很昂贵。绑定变量也存在问题,perlsyn建议完全避免这种情况。

答案 4 :(得分:1)

我不知道如何在foreach语句本身中强制变量为by-value而不是by-reference。您可以复制$_的值。

#!/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__

答案 5 :(得分:0)

在for语句中复制@list:

foreach my $var1 (() = @list) {
  # modify $var without modifying @list here
}