Ruby中的变量范围

时间:2015-11-24 17:57:33

标签: ruby

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

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

由于

2 个答案:

答案 0 :(得分:5)

不同之处在于if块实际上并不像Java中的其他语言那样是一个单独的范围。在if块内声明的变量与周围环境具有相同的范围。现在,在您的情况下,if块实际上没有被执行,因此您通常期望d未定义(导致您在第二个示例中遇到的相同错误) )。但红宝石有点&#34; smrt&#34;因为它不管是否实际执行,解释器将在它看到它的那一刻设置一个具有该标签的变量,因为它实际上还不知道该分支是否确实会执行。 David Flanagan和Yukihiro Matsumoto在"The Ruby Programming Language"中解释了这一点(不能复制粘贴文本,添加截图): enter image description here

对于.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

相关问题