在Ruby中为什么不会`foo = true除非定义?(foo)`进行赋值?

far*_*adf 14 ruby

这里发生了什么?两种形式"除非"之间的细微差别是什么?

> irb(main):001:0> foo = true unless defined?(foo)
=> nil 
irb(main):002:0> unless defined?(fooo) ; fooo = false ; end
=> false 
Run Code Online (Sandbox Code Playgroud)

谢谢

Yan*_*nik 16

显然,ruby在解析时创建局部变量,将它们设置nil为定义,无论代码是否执行,都会执行此操作.

在第一行评估代码时,它不会执行赋值部分,因为foo设置为nil.在第二行中,因为fooo尚未解析,所以defined?返回nil让块内的代码执行并分配fooo.

举个例子,你可以尝试这个:

if false  
  foo = 43  
end  
defined? foo  
=> "local-variable"
Run Code Online (Sandbox Code Playgroud)

这是从ruby-forum 的论坛帖子中获取的.


FMc*_*FMc 12

让我们从更简单的事情开始:

# z is not yet defined
irb(main):001:0> defined?(z)
=> nil

# Even though the assignment won't execute,
# the mere presence of the assignment statement
# causes z to come to life.
irb(main):002:0> z = 123 if false
=> nil
irb(main):003:0> defined?(z)
=> "local-variable"
irb(main):004:0> z
=> nil
Run Code Online (Sandbox Code Playgroud)

现在我们可以找出你的第一个例子.

foo = true unless defined?(foo)
Run Code Online (Sandbox Code Playgroud)

foo定义?在我们按ENTER之前irb,没有.但是,赋值语句的存在会导致foo生命.这意味着赋值语句将不会被执行,foo而是存在但具有nil其值.那irb行中评估的最后一个表达式是什么?它是unless defined?(foo),评估为nil.

有关如何分配(甚至那些未执行的分配)导致变量存在的更多信息,请参阅变量/方法歧义的讨论.

在你的第二个例子中,没有任何神秘的东西:fooo未定义,因此块中的代码执行,设置fooofalse.该赋值是最后一个求false值表达式,也就是块的返回值.