和this question一样,当一个没有定义的局部变量在它自己的赋值中使用时,它的值为nil
。
x = x # => nil
字符串
但是当一个局部变量的名字与一个已有的方法名字冲突时,就比较棘手了。为什么下面的最后一个例子会返回nil
?
{}.instance_eval{a = keys} # => []
{}.instance_eval{keys = self.keys} # => []
{}.instance_eval{keys = keys} # => nil
型
和this question一样,当一个没有定义的局部变量在它自己的赋值中使用时,它的值为nil
。
x = x # => nil
字符串
但是当一个局部变量的名字与一个已有的方法名字冲突时,就比较棘手了。为什么下面的最后一个例子会返回nil
?
{}.instance_eval{a = keys} # => []
{}.instance_eval{keys = self.keys} # => []
{}.instance_eval{keys = keys} # => nil
型
4条答案
按热度按时间6za6bjd01#
在Ruby中,因为方法可以在没有显式接收器和括号的情况下调用,所以局部变量引用和无接收器无参数方法调用之间存在语法上的歧义:
字符串
可以 either 表示“调用方法
foo
onself
with no arguments”或“解引用局部变量foo
“。如果作用域中存在一个局部变量
foo
,这 * 总是 * 被解释为局部变量解引用,* 从不 * 被解释为方法调用。那么,局部变量“在作用域中”意味着什么呢?这是在 * 解析时 * 从语法上 * 确定的,而不是在运行时从语义上确定的。这非常重要!局部变量是在解析时定义的:如果解析器看到了对局部变量的赋值,则局部变量从该点起就在作用域中。然而,它只在运行时 * 初始化 *,没有对代码进行编译时评估:
型
为什么局部变量可以“隐藏”方法而不是其他方法呢?如果方法隐藏了局部变量,那么就没有办法对这些局部变量进行解引用了。但是,如果局部变量隐藏了方法,那么仍然有办法调用这些方法:记住,这种二义性只存在于receiverless argumentless方法调用中,如果你添加了一个显式的receiver或一个显式的参数列表,你仍然可以调用该方法:
型
tjvv9vkg2#
简短的回答是,因为Matz是这样定义的。这种行为是我不喜欢Ruby的少数几件事之一。它甚至变得更好:
字符串
变量
a
被初始化为nil,即使理论上a = b语句在任何情况下都不应该被执行。uhry853o3#
我采用这种模式是为了确保作用域符合我的预期,而不会在没有大量
self
的情况下污染代码库字符串
myzjeezk4#
我认为在你的情况下,这是因为它是什么的预期:P
字符串
示例eval在示例级别评估代码,因此您声明的每个散列都是不同的。
型