Ruby中的变量范围

Raz*_*aza 5 ruby

考虑以下两个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)

为什么在第一种情况下打印空白而第二种情况会抛出错误?

谢谢

Pau*_*ter 5

区别在于if块实际上不是像Java那样的其他语言中的单独范围.if块内声明的变量与周围环境的范围相同.现在,在您的情况下,该if块实际上不会被执行,因此您通常期望d未定义(导致您在第二个示例中得到的相同错误).但ruby有点"smrt",因为解释器会在它看到它的那一刻设置一个带有该标签的变量,无论它是否实际执行,因为它实际上还不知道该分支是否确实会执行.这在David Flanagan和Yukihiro Matsumoto的"The Ruby Programming Language"中有解释(不能复制粘贴文本,而是添加截图): 在此输入图像描述

.each循环的情况下,do...end您编写的实际上是一个,它确实有自己的局部范围.换句话说,块内声明的变量只对该块是本地的.

但是,块"继承"它们声明的环境的范围,因此您可以做的是flag.each迭代块之外声明,然后块将能够访问它并设置其值.请注意,在您给出的示例中,这不会发生,因为您尝试迭代空数组,但至少您不会再收到错误.

一些额外的阅读: