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

a未定义时,则为a || 1 a || 1将抛出错误,但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 '' 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 '' irb(main):003:0> a = a || 1 => 1 

 a 

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

 a || 1 

在这里,您仍然需要评估a来确定布尔表达式的值。 如上所述, a未定义。 因此,你得到一个例外。

 a = a || 1 

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

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

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

当你做a || 1 a || 1 ,你要求它寻找未定义的a的值。

当你做a = a || 1 a = a || 1你要求它寻找分配给a似乎没有给出错误的a的值。

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

你是这个意思吗?

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

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