今天我遇到了Ruby的内联if和奇怪的行为if和阻止if
2.0.0-p247 :001 > inline_if = 'value will not set but no error' if inline_if
=> nil
2.0.0-p247 :002 > if block_if
2.0.0-p247 :003?> block_if = 'forget about setting value, I will raise an error'
2.0.0-p247 :004?> end
NameError: undefined local variable or method `block_if' for main:Object
from (irb):2
from /Users/myuser/.rvm/rubies/ruby-2.0.0-p247/bin/irb:13:in `<main>'
如果是条件的内联和有条件的阻塞之间有什么区别?
答案 0 :(得分:2)
我怀疑它与ruby解析器有关。因为在写内联时
inline_if = 'value will not set but no error' if inline_if
Ruby解析器实际上从左到右解析。所以在上面的行中它首先遇到变量inline_if
的setter方法。所以它实际上用值nil
定义了这个变量,然后检查条件if inline_if
,它将被评估为if nil
。
现在使用阻止条件
if block_if
block_if = 'forget about setting value, I will raise an error'
end
它首先尝试访问尚未定义的block_if
变量。因此它会抛出一个错误。
令人惊讶的是,从程序员的角度来看,上述两个块都应该被平等地评估。但他们表现不同
答案 1 :(得分:2)
请参阅Local Variables and Methods:
当解析器遇到赋值时创建局部变量,而不是在赋值发生时创建:
a = 0 if false # does not assign to a p local_variables # prints [:a] p a # prints nil
在第一个示例中,inline_if
在赋值时首先遇到,因此创建它(并且值为nil
)。在第二个示例中,block_if
在分配中看到之前的条件中出现,这会导致错误。
答案 2 :(得分:1)
&#34; Ruby解释器在看到对它的赋值时用nil初始化一个局部变量。&#34;请参阅this answer一个相关的简单问题,该问题突出了您所看到的行为的关键部分。
> a = a
# => nil (and assigns nil to a)
> b = c
# => NameError...
另外,请注意关于JavaScript和Ruby奇怪的这个热闹的video!