我不明白ruby的本地范围

在这个例子中,

def foo(x) if(x > 5) bar = 100 end puts bar end 

然后foo(6)输出:100和foo(3)什么都不输出。

但是,如果我改变了定义

 def foo(x) if(x > 5) bar = 100 end puts bob end 

我得到一个“未定义的本地variables或方法”错误。

所以我的问题是为什么我没有得到这个错误,当我打电话富(3)和酒吧从未设置?

有几件事情在这里发生。 首先,在if块中声明的variables与在方法顶层声明的variables具有相同的局部范围,这就是为什么barif外部可用的原因。 其次,你会得到这个错误,因为bob是被直接引用的。 Ruby解释器从来没有见过它,从来没有见过它初始化之前。 但是,在if语句之前,它已经看到了bar初始化。 所以什么时候得到禁止它知道它存在。 结合这两个,这就是你的答案。

你的第二个例子实际上是一个红鲱鱼:你得到一个exception的原因不是因为bob是未初始化的,这是因为它是模糊的。 不可能判断它是一个variables还是一个方法。

你的第一个例子工作,因为未初始化的本地variables(以及全局variables和实例variables)计算nil 。 因此, puts bar是完全正确的:在一种情况下, bar被初始化为100并且这个值为100 ,在另一种情况下,它是未初始化的,因此评估nilputs它的参数调用to_s ,这个参数定义为nil (它只是返回空string),所以一切都很好,很花哨。

另请参阅在Ruby中,为什么在启动irb之后,foo.nil? 说未定义的错误,和@ foo.nil? 给出“真实”,和@@ wah.nil? 再次发生错误?

所以不要把它当做福音(因为它更多的是基于观察和理解),但是似乎ruby解释器会在等号的左边标记任何单词(前面没有印记)作为本地。 你的例子很奇怪,这更奇怪

 def foo bar = bar puts bar // nil, which gets coerced into "" end 

我不明白为什么或者它是如何工作的,但是在那里。

foo(3)不会输出任何内容。 它输出一个换行符。

使用inspect会给你更多的提示:

 def foo(x) if(x > 5) bar = 100 end puts bar.inspect end foo(3) 

打印出来

 nil 

bar是一个完全成熟的variables,恰好有nil的值。

我不确定你在问什么 用第二个定义运行foo(3)总会给出一个错误,因为bob永远不会被定义。 该方法的论点不会改变这一点。