关于是否bar
定义没有区别。在这两种情况下,bar
在正文中都是未定义的。但是,在后一种情况下,从不评估身体,因此没关系。您永远不会解析 name bar
,因此在名称解析期间永远不会出错。
局部变量是在解析赋值时定义的。它们在执行分配时被初始化。
将变量统一化是非常好的。在这种情况下,它只会评估为nil
:
if false
bar = 42
end
bar
# => nil
然而,如果变量是undefined,那么 Ruby 不知道一个裸词是一个局部变量还是一个无接收的无参数消息发送:
foo
# NameError: undefined local variable or method `foo'
# ^^^^^^^^^
# Ruby doesn't know whether it's a variable or a message send
与之比较:
foo()
# NoMethodError: undefined method `foo'
# ^^^^^^^^^^^^^
self.foo
# NoMethodError: undefined method `foo'
# ^^^^^^^^^^^^^
现在都在一起了:
foo()
# NoMethodError: undefined method `foo'
self.foo
# NoMethodError: undefined method `foo'
foo
# NameError: undefined local variable or method `foo'
if false
foo = 42
end
foo
# => nil
foo = :fortytwo
foo
# => :fortytwo
在这种特殊情况下,问题在于解析表达式的顺序(以及定义变量的顺序)与执行表达式的顺序不匹配。
分配首先执行,这将使您假设bar
将在正文中定义。但事实并非如此,因为首先解析了主体,因此在看到赋值之前,我不知道这是一个方法还是一个变量节点被插入到语法树中。
但是,如果从不解释该节点,即条件为假,则不会发生任何不好的事情。