为什么以下代码不会抛出错误?
if false
x = 0
end
x #=> nil
以下情况会引发错误:
y # NameError: undefined local variable or method `x' for main:Object
同样的事情发生在unless
& case
陈述。
答案 0 :(得分:20)
这是因为Ruby解析器的工作原理。变量由解析器定义,解析器逐行遍历代码,无论它是否实际执行。
解析器看到x =
后,它会在当前范围内定义局部变量x
(值为nil
)。由于if
/ unless
/ case
/ for
/ while
未创建新范围,因此x
已在代码块之外定义并可用。并且由于内部块永远不会被评估为条件为假,因此x
未分配给(nil
}。
这是一个类似的例子:
defined?(x) and x = 0
x #=> nil
请注意,这是对所发生情况的高级概述,并不一定是解析器的工作方式。
答案 1 :(得分:2)
这与Ruby的范围规则的怪癖有关。
在ruby中,一个未修饰的变量x
本身可能是局部变量或方法调用 - 语法无法分辨哪个。由解析器解析局部变量引用,由解析器决定。规则很简单:如果已经在本地范围内看到对同名变量的赋值,则引用是局部变量,并且引用绑定到该局部变量。否则,它是一个方法调用,它将在运行时被查找。
Ruby中的局部变量引用被优化为数组查找(每个局部变量被赋予一个'slot',并且由解析器生成的绑定局部变量引用被转换为槽引用)。使用所有nil
初始化数组:
/* initialize local variables */
for (i=0; i < local_size; i++) {
*sp++ = Qnil;
}
因此,如果您引用尚未分配的局部变量,则通过绑定的本地引用(只有在同一本地范围内的引用之上有跳过的赋值时才会发生),您得到{{1 }}
答案 2 :(得分:1)
我觉得你的问题很有趣所以我试着查一下,发现了这个: I don't understand ruby local scope
正确的答案似乎是Jorg。
让我们看一下当您尝试访问未初始化的变量时会发生什么:
NameError: undefined local variable or method `UNDECLAREDVAR' for main:Object
该异常表明它无法评估变量或方法。它没有抛出相同异常的原因是因为未初始化的局部变量设置为nil。所以puts x
是可以的,因为解释器知道x
是可变的但未初始化而不是方法。