Ruby 循环局部变量和不可变性

Nav*_*rro 0 ruby functional-programming

我有以下代码:

# Assuming each element in foo is an array.
foo.each do |bar|
  zaz = bar.first
  # Other code using zaz, but not modifying it.
end
Run Code Online (Sandbox Code Playgroud)

局部变量是否会zaz在循环内的每次迭代中被修改,使其可变?我不确定 Ruby 在这里的行为。

Jör*_*tag 5

实际上,这取决于循环之前的代码。

\n\n

如果这就是全部代码,那么zaz就是一个块局部变量,并且每次评估循环体时都会创建一个新变量。 zaz

\n\n

然而,如果zaz周围作用域中有一个局部变量,那么zaz块中的变量就是一个自由变量,并且由于块作用域嵌套在其周围作用域中,因此zaz块外部的现有变量将被一遍又一遍地重新分配,每次评估块的时间。

\n\n

您可以zaz通过在块的参数列表中显式地将其声明为块局部变量,确保始终将其视为块局部变量并且永远不会在周围范围中查找:

\n\n
foo.each do |bar; zaz|\n  zaz = bar.first\nend\n
Run Code Online (Sandbox Code Playgroud)\n\n

但请注意,只有当您的代码不纯且可变时,您的代码才有意义:

\n\n
    \n
  1. 您分配zaz但从未在块内实际使用它。因此,唯一有意义的方法是,如果它zaz是外部作用域中的局部变量,并且您正在为其赋值。尽管在这种情况下,您的整个循环仅相当于zaz = foo.last.first.
  2. \n
  3. each仅评估块的副作用。没有副作用,each根本没有任何意义,所以你使用的事实each就意味着你有副作用。
  4. \n
\n\n
\n\n

请注意,没有附加限定的术语“不可变”通常指的是值。当谈论“不可变变量”时,我们通常会明确地说“不可变变量”,以表明我们只是在谈论变量是否可以重新绑定,而不是在谈论改变对象状态。或者,可以直接说“常量”,这是“不可变变量”\xe2\x80\xa6 的技术术语,尽管该术语在 Ruby 中已经具有特定含义。

\n