9

所以,我从来不知道这一点,我想澄清一下。我知道如果你这样做

foreach (@list){

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

foreach my $var1 (@list){

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

4

6 回答 6

10

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

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

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

于 2009-06-18T15:22:25.363 回答
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 是一个大数据结构,它可能会很昂贵。

于 2009-06-18T15:21:45.143 回答
4

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

于 2009-06-18T15:51:46.607 回答
2

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

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

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

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

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

这适用于普通的标量值。对于引用(或对象),您需要使用StorableClone进行深层复制,这可能会很昂贵。绑定变量也是有问题的,perlsyn建议完全避免这种情况。

于 2009-06-18T16:26:50.497 回答
1

我不知道如何在 foreach 语句本身中强制变量按值而不是按引用。你可以复制$_虽然的值。

#!/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__
于 2009-06-18T15:22:55.423 回答
1

在 for 语句中复制@list:

foreach my $var1 (() = @list) {
  # modify $var without modifying @list here
}
于 2011-09-10T04:23:00.273 回答