2010-06-06 88 views
7

a是不确定的,那么a || 1将抛出一个错误,但a = a || 1不会。这是不是有点不一致?为什么在Ruby中,|| 1在未定义a时会引发错误,但a = a || 1不会?

irb(main):001:0> a 
NameError: undefined local variable or method 'a' for main:Object 
     from (irb):1 
     from c:/ruby/bin/irb:12:in '<main>' 

irb(main):002:0> a || 1 
NameError: undefined local variable or method 'a' for main:Object 
     from (irb):2 
     from c:/ruby/bin/irb:12:in '<main>' 

irb(main):003:0> a = a || 1 
=> 1 
+0

重复http://stackoverflow.com/questions/1462407/ruby-edge-cases的 – 2010-06-06 23:20:52

回答

9
a 

在这里,你正在评估a,这是没有定义。因此,你会得到一个异常。

a || 1 

在这里,你仍然必须评估a确定布尔表达式的值。就像上面一样,a没有定义。因此,你会得到一个异常。

a = a || 1 

这里,a是定义。它被定义为一个未初始化的局部变量。在Ruby中,未初始化的变量计算为nil,因此赋值表达式的右侧计算结果为nil || 1,计算结果为1,因此赋值表达式的返回值为1,副作用为a初始化为1

编辑:似乎有当变量得到定义,当他们在Ruby中得到初始化上有些混乱。在解析时间定义的获得,但在运行时初始化。您可以在此处看到:

foo # => NameError: undefined local variable or method `foo' for main:Object 

foo未定义。

if false 
    foo = 'This will never get executed' 
end 

此时,foo被定义,即使该行永远不会被执行。线从未被执行的事实是完全不相关的,因为解释器无论如何都与此无关:局部变量由解析器定义,并且解析器显然看到了这一行。

foo # => nil 

没有错误,因为foo定义,它的计算结果为nil,因为它是未初始化。

+0

+1,但我想说“它被定义为未初始化的局部变量”。有点混乱。当你做'var = expr'时,你没有定义'var'被初始化。你将var定义为'expr'的值。只是'expr'评估时,'var'恰好是未初始化的,这意味着'expr'内'var'的任何引用都将评估为零。 – sepp2k 2010-06-06 09:50:08

+1

@ sepp2k:他们是两个非常独立的步骤。变量定义发生在解析器中,在解释器中初始化。根据Ruby的实现,这两个事件之间可能会有相当长的时间。例如,在BlueRuby中,当你安装一个Ruby程序时,Ruby源代码被解析成BRIL(BlueRuby中间语言),然后存储在数据库中。它可能是*年*,直到有人真正运行程序。所有这些时间,变量都已定义,但未初始化。这两件事情甚至可能发生在不同的机器上。 – 2010-06-06 10:26:36

1

当你做a || 1,你问它来寻找的a其价值是不确定的。

当你做a = a || 1你要它寻找aa这似乎并没有错误的价值。

所以,虽然很奇怪,我不认为它是不一致的。

+0

这是不对的。'a = a || 1'不解析为'(a = a)|| 1'。它解析为'a =(a || 1)',所以“赋a给a”的结果与它无关,因为a永远不会分配给a。 – sepp2k 2010-06-06 09:46:17

+0

@ sepp2k:我并没有试图暗示这一点。如果我迷惑你,我很抱歉。我相信Jörg已经更清楚地解释了它。 – Cetra 2010-06-06 14:25:07

0

这是你的意思吗?

if !(defined? a) then 
    a = 1 
end 

将值1声明为默认值可能会更简单。

相关问题