这里发生了什么?两种形式“除非”之间的细微差别是什么?
> irb(main):001:0> foo = true unless defined?(foo)
=> nil
irb(main):002:0> unless defined?(fooo) ; fooo = false ; end
=> false
THX
答案 0 :(得分:16)
显然,ruby在解析时创建局部变量,将它们设置为nil
,因此它已定义,无论代码是否执行,都会执行此操作。
在第一行评估代码时,由于foo
设置为nil
,因此不会执行分配部分。在第二行中,由于尚未解析fooo
,defined?
返回nil
,让块内的代码执行并分配fooo
。
举个例子,你可以试试这个:
if false
foo = 43
end
defined? foo
=> "local-variable"
这是来自ruby-forum的论坛post。
答案 1 :(得分: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
现在我们可以找出你的第一个例子。
foo = true unless defined?(foo)
是否定义了foo
?在我们按irb
中的ENTER之前,没有。但是,赋值语句的存在会导致foo
生效。这意味着赋值语句不会执行,foo
存在,但nil
为其值。什么是irb
行中评估的最后一个表达式?它是unless defined?(foo)
,其评估结果为nil
。
有关如何分配(甚至那些未执行的分配)导致变量存在的更多信息,请参阅Variable/Method Ambiguity的讨论。
在你的第二个例子中,没有任何神秘之处:fooo
未定义,因此块中的代码执行,将fooo
设置为false
。该赋值是最后一个求值表达式,因此false
是块的返回值。
答案 2 :(得分:2)
irb(main)> foo = true unless defined?(Integer)
=> nil
irb(main)> foo = true unless defined?(thisIsUndefined)
=> true
你的第一个区块正在返回nil
,因为它的编写方式有两个选项:
foo
未定义 - >指定真实foo
已定义 - >什么都不做这里,必须在评估线时定义foo。因此,没有任何反应,并返回nil
。
irb(main)> unless defined?(Integer) ; fooo = false ; end
=> nil
irb(main)> unless defined?(thisIsUndefined) ; fooo = false ; end
=> false
你的第二个街区的运作方式与第一个街区相同。如果未定义fooo
,则会输入阻止,fooo
设置为false
。块的最后一行的结果是块的返回值,因此您看到的是false
。如果fooo
确实存在,则跳过该块并且没有任何反应,因此无法返回,因此nil
。
根据您的代码,我会说在运行此代码时foo
已定义且fooo
未运行(显示的测试代码是在Ruby 1.8.6中生成的)。如果在运行此代码之前没有定义其中任何一个,那么您可能会默认定义一个名为foo
的内容(单独执行defined?(foo)
来检查)。尝试使用其他名称,看看是否得到相同的结果。
修改强>
irb(main)> defined?(bar)
=> nil
irb(main)> bar = true unless defined?(bar)
=> nil
irb(main)> defined?(bar)
=> "local-variable"
显然,defined?()
返回true,因为它已经看到bar
(在行的开头),即使您仍在定义它。
答案 3 :(得分:1)
在第一个实例中,您在赋值语句中调用foo
。也许这会澄清:
bar = if true
puts bar.class
else
puts "not reached"
end
NilClass
=> nil
baz = if true
puts baz.class
42
else
puts "not reached"
end
NilClass
=> 42
答案 4 :(得分:1)
$ irb
irb(main):001:0> unless defined?(fooo); fooo = true; end
=> true
irb(main):002:0> fooo
=> true
irb(main):003:0> `ruby --version`
=> "ruby 1.8.7 (2008-06-20 patchlevel 22) [i486-linux]\n"
答案 5 :(得分:-1)
嗯..一个表单是一个块而一个表单不是。第二部分,块,返回评估的最后一个语句。第一个...... Hrm ..我不确切知道它在做什么。
答案 6 :(得分:-1)
在Ruby 1.8.7中:
foo = true unless defined?(foo)
p foo # => nil
unless defined?(fooo); fooo = true; end
p foo # => nil
我对你所看到的行为没有解释。