【问题标题】:perl foreach loop in subroutine子例程中的perl foreach循环
【发布时间】:2014-06-07 12:23:50
【问题描述】:

我知道 perl 中的子例程通过引用传递 arg。但是在下面的代码中,子例程中的 foreach 循环不应该更改 @list 的值,因为 my $i 应该创建一个新的词法范围 var $i。对$i 的任何赋值都应该是词法范围,但不能更改@list 的值。

谁能解释导致值更改为@list 的foreach 循环内部发生了什么?

sub absList {    
    foreach my $i (@_) {
        $i = abs($i);
    }
}

@list = (-2,2,4,-4);
absList(@list);
print "@list";

输出:

2 2 4 4

【问题讨论】:

    标签: perl foreach subroutine


    【解决方案1】:

    $iforeach 特性而被别名为@_ 数组的元素(而@_ 元素被别名为@list@_ magic 的元素)。

    来自perldoc

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

    如果你想避免这种行为,不要直接遍历@_数组,即。

    sub absList {
        my @arr = @_;
        foreach my $i (@arr) {
            $i = abs($i);
        }
    }
    

    【讨论】:

    • 感谢信息的链接。所以这意味着无论我使用/不使用my,foreach 中的$i 将始终被引用/别名为@arr。如果@arr 是特殊变量@_,则意味着$i 将是@_ 中元素的实际值。将任何值分配给$i 意味着更改$@ 中元素的值。我说的对吗?
    • @user2763829 是的,my 只定义了迭代变量的范围。
    • 谢谢。即使在foreach 中没有my$i 将始终在foreach 循环内限定范围,因为$i 将在本地范围内。那么实际上是否需要将my 声明为$i(在这种情况下或任何其他情况下)?
    • @user2763829 如果你使用推荐的strict,那么你必须在某个地方声明$i,perl 的最佳实践是将每个变量的范围限制在它所在的最小块中实际使用。这导致foreach my $i (..)
    • 或:sub absList { foreach my $i (@_) { my $j = abs($i); ... } }
    【解决方案2】:

    $i 这里指的是它从@_ 获得的列表元素,这就是为什么更改$i 会导致相应列表元素发生变化。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-10-20
      • 2013-10-04
      • 1970-01-01
      • 2016-12-04
      • 2023-04-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多