考虑以下两个ruby代码片段。
puts "One"
if false
d = 1
end
puts "Two"
puts d
puts "Three"
这将打印以下内容
One
Two
Three
现在,请考虑以下
[].each do |i|
flag = false
end
puts "Two"
puts flag
puts "Three"
这给出了以下
Two
'<main>': undefined local variable or method 'flag' for main:Object (NameError)
为什么在第一种情况下会打印一个空白而第二种情况会抛出错误?
由于
答案 0 :(得分:5)
不同之处在于if
块实际上并不像Java中的其他语言那样是一个单独的范围。在if
块内声明的变量与周围环境具有相同的范围。现在,在您的情况下,if
块实际上没有被执行,因此您通常期望d
未定义(导致您在第二个示例中遇到的相同错误) )。但红宝石有点&#34; smrt&#34;因为它不管是否实际执行,解释器将在它看到它的那一刻设置一个具有该标签的变量,因为它实际上还不知道该分支是否确实会执行。 David Flanagan和Yukihiro Matsumoto在"The Ruby Programming Language"中解释了这一点(不能复制粘贴文本,添加截图):
对于.each
循环,您写入的do...end
实际上是block, 有自己的flag
当地范围。换句话说,块内声明的变量只对该块是本地的。
然而,块&#34;继承&#34;他们声明的环境范围,所以你可以做的是在.each
迭代块之外声明public MyModel(){
Comments = new HashSet<Comm_ent>();
}
,然后块就可以访问它并设置它值。请注意,在您给出的示例中,由于您尝试迭代空数组而不会发生这种情况,但至少您不会再收到错误。< / p>
一些额外的阅读:
答案 1 :(得分:2)
在Ruby中,当你对一个变量赋值(在你的情况下是my ($stdout, $stderr, $exit) = capture {
system('2166_PG_Upload_Batch.bat');
};
#check for $stderr and do your stuffs i.e sending email etc
)在If语句的False-branch中的任何地方时,它声明了这个变量,除非定义了方法d
。 False-branch中的d=
基本上是这样的:b = bla-bla-bla
。
在空数组上使用块时,没有任何反应。如果数组不为空,则变量仍然是块的当前迭代的局部变量,除非它是在块范围之外定义的,例如:
b = nil
NameError:未定义的局部变量或方法`a',用于main:Object
[1,2,3,4].each do |i|
a=i
end
puts a
4
如果之前已经定义了a=1
[1,2,3,4].each do |i|
a=i
end
puts a
,那么你可以选择在一个区块内使用a
作为本地区域:
a=1
[1,2,3,4].each do |i; a|
a=i
end
puts a
1