我不明白ruby本地范围

时间:2010-11-11 13:27:00

标签: 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

我收到“未定义的局部变量或方法”错误。

所以我的问题是为什么当我调用foo(3)并且从未设置bar时我没有收到此错误?

5 个答案:

答案 0 :(得分:55)

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

答案 1 :(得分:15)

你的第二个例子实际上是一个红色鲱鱼:你获得异常的原因不是因为bob未初始化,而是因为它含糊不清。无法判断它是变量还是方法。

您的第一个示例有效,因为未初始化的局部变量(以及全局变量和实例变量)计算为nil。因此,puts bar完全正常:在一种情况下,bar初始化为100,此评估为100,在另一种情况下,它未初始化,因此评估为{{ 1}}。 nil在其参数上调用puts,该参数是为to_s定义的(它只返回空字符串),所以一切都很好而花花公子。

另见In Ruby, why after starting irb, foo.nil? says undefined error, and @foo.nil? gives “true”, and @@wah.nil? gives error again?

答案 2 :(得分:4)

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

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

我不明白为什么或如何运作,但你有它。

答案 3 :(得分:2)

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

使用inspect会给你更多提示:

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

foo(3)

打印出来

nil

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

答案 4 :(得分:0)

我不确定你在问什么。使用第二个定义运行foo(3)将始终给出错误,因为永远不会定义bob。该方法的参数不会改变它。