||的奇怪含义和|| =在Ruby中(2.0,1.9.3,jruby 1.7.4)

时间:2013-10-25 16:38:55

标签: ruby jruby

从新开始的会话中考虑以下irb片段:

irb:01> baz            # => NameError, baz is not defined
irb:02> baz || baz = 0 # => NameError, baz is not defined
irb:03> baz            # => nil

baz是一个未定义的变量,尝试评估它会产生NameError。然而,不知何故,在此操作之后,baz被定义,其值为nil。看起来,值nil已分配给变量baz,即使没有人(明确地)要求它。是否存在潜在的语言原因,为什么这种行为是可取的?

解释此行为和其他类似令人困惑的结构的规则是什么,例如:

irb:04> true if foo            # => NameError
irb:05> foo                    # => NameError; name still undefined
irb:06> foo = (true if foo)    # => nil
irb:07> foo                    # => nil; name defined as nil
irb:08> true || i = 0 || j = 2 # => i and j are nil; || appears nonlazy
irb:09> raise || quux = 1      # => RuntimeError, quux is nil

1 个答案:

答案 0 :(得分:9)

我不知道它是否可取,但它来自Ruby如何解析代码。只要有一段代码分配局部变量,即使未评估该段代码,也会为该局部变量分配nil。在您的代码行2中:

baz || baz = 0

第一个baz返回错误,因为没有分配这样的变量。因此,其后的作业baz = 0 未评估,但仍然是已解析,因此在接下来的上下文中,本地变量baz已创建,并初始化为nil

使用第二个代码块时,footrue if foo期间未分配foo。在此之后,foo = (true if foo)已分配给foo,因此,即使在(true if foo)的分配之前评估foo,也不会在该行中引发错误。