10

考虑一下新开始的会话中的以下 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
4

1 回答 1

9

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

baz || baz = 0

第一个baz返回错误,因为没有分配这样的变量。因此,它后面的赋值baz = 0没有被评估,但它被解析了,所以在后面的上下文中,创建了一个局部变量baz,并初始化为nil

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

于 2013-10-25T16:54:49.140 回答