考虑以下两个ruby代码片段.
puts "One"
if false
d = 1
end
puts "Two"
puts d
puts "Three"
Run Code Online (Sandbox Code Playgroud)
这将打印以下内容
One
Two
Three
Run Code Online (Sandbox Code Playgroud)
现在,请考虑以下内容
[].each do |i|
flag = false
end
puts "Two"
puts flag
puts "Three"
Run Code Online (Sandbox Code Playgroud)
这给出了以下内容
Two
'<main>': undefined local variable or method 'flag' for main:Object (NameError)
Run Code Online (Sandbox Code Playgroud)
为什么在第一种情况下打印空白而第二种情况会抛出错误?
谢谢
区别在于if块实际上不是像Java那样的其他语言中的单独范围.if块内声明的变量与周围环境的范围相同.现在,在您的情况下,该if块实际上不会被执行,因此您通常期望d未定义(导致您在第二个示例中得到的相同错误).但ruby有点"smrt",因为解释器会在它看到它的那一刻设置一个带有该标签的变量,无论它是否实际执行,因为它实际上还不知道该分支是否确实会执行.这在David Flanagan和Yukihiro Matsumoto的"The Ruby Programming Language"中有解释(不能复制粘贴文本,而是添加截图):

在.each循环的情况下,do...end您编写的实际上是一个块,它确实有自己的局部范围.换句话说,块内声明的变量只对该块是本地的.
但是,块"继承"它们声明的环境的范围,因此您可以做的是flag在.each迭代块之外声明,然后块将能够访问它并设置其值.请注意,在您给出的示例中,这不会发生,因为您尝试迭代空数组,但至少您不会再收到错误.
一些额外的阅读: