为什么在Ruby中,当a未定义时,a | | 1会抛出错误,而a=a | | 1不会?
当为什么在Ruby中,当a未定义时,a | | 1会抛出错误,而a=a | | 1不会?,ruby,exception,undefined,undefined-behavior,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
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
irb(main):001:0>a
NameError:未定义的局部变量或main:对象的方法“a”
来自(irb):1
来自c:/ruby/bin/irb:12:in''
irb(主要):002:0>a | | 1
NameError:未定义的局部变量或main:对象的方法“a”
来自(irb):2
来自c:/ruby/bin/irb:12:in''
irb(主):003:0>a=a | | 1
=> 1
执行a | | 1
时,要求它查找未定义的a
的值
if false
foo = 'This will never get executed'
end
当您执行a=a | | 1
时,您要求它查找将a
赋值给a
的值,该值似乎不会给出错误
所以,虽然很奇怪,但我不认为这是不一致的。这就是你的意思吗
if !(defined? a) then
a = 1
end
使用1作为默认值来声明值可能更简单
a
这里,您正在评估未定义的a
。因此,您会得到一个例外
a || 1
a = a || 1
在这里,您仍然需要计算a
,以确定布尔表达式的值。与上面一样,a
没有定义。因此,您会得到一个例外
a || 1
a = a || 1
这里定义了a
。它被定义为未初始化的局部变量。在Ruby中,未初始化变量的值为nil
,因此赋值表达式的右侧值为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=a | | 1
不解析为(a=a)| | 1
。它解析为a=(a | | 1)
,因此“将a分配给a”的结果与此无关,因为a从未分配给a。@sepp2k:我根本不想暗示这一点。对不起,我把你弄糊涂了。我相信Jörg已经解释得更清楚了。+1,尽管我认为说“它被定义为一个未初始化的局部变量”有点混乱。当您执行var=expr
时,您并没有将var
定义为未初始化。您将var定义为expr
的值。只是当expr
求值时,var
恰好未初始化,这意味着expr
中对var
的任何引用都将求值为零。@sepp2k:这是两个非常独立的步骤。变量定义发生在解析器中,初始化发生在解释器中。根据Ruby实现的不同,这两个事件之间可能有很长的时间间隔。例如,在BlueRuby中,Ruby源代码被解析为BRIL(BlueRuby中间语言),当您安装Ruby程序时,BRIL被存储在数据库中。可能要过几年才会有人真正运行这个程序。一直以来,变量都已定义但未初始化。这两件事甚至可能发生在不同的机器上