为什么在Ruby中,||当`a`未定义时,1会抛出错误,但a = a || 1会不会?

时间:2010-06-06 06:54:51

标签: ruby exception undefined undefined-behavior

如果a未定义,则a || 1会抛出错误,但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

3 个答案:

答案 0 :(得分:9)

a

在这里,您正在评估未定义的a。因此,你得到一个例外。

a || 1

在这里,必须评估a以确定布尔表达式的值。如上所述,a未定义。因此,你得到一个例外。

a = a || 1

此处,a 已定义。它被定义为未初始化的局部变量。在Ruby中,未初始化的变量求值为nil,因此赋值表达式的右侧求值为nil || 1,其求值为1,因此赋值表达式的返回值为{{1副作用是1被初始化为a

编辑:似乎在变量定义时以及在Ruby中初始化时存在一些混淆。 get定义在解析时,但在运行时初始化。你可以在这里看到它:

1

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,因为它未初始化。

答案 1 :(得分:1)

执行a || 1时,您要求它查找未定义的a的值。

执行a = a || 1时,您要求它查找将a分配给a的值,这似乎不会出错。

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

答案 2 :(得分:0)

这是你的意思吗?

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

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