问题描述
与此问题中一样,如果未在其自己的分配中使用未定义的局部变量,则会将其评估为nil
As in this question, when a local variable not defined is used within its own assignment, it is evaluated to nil
.
x = x # => nil
但是,当局部变量的名称与现有的方法名称冲突时,它会更加棘手.为什么下面的最后一个示例返回nil
?
But when the name of a local variable conflicts with an existing method name, it is more tricky. Why does the last example below return nil
?
{}.instance_eval{a = keys} # => []
{}.instance_eval{keys = self.keys} # => []
{}.instance_eval{keys = keys} # => nil
推荐答案
在Ruby中,由于可以在没有显式接收器且没有括号的情况下调用方法,因此局部变量引用与无接收器无参数方法调用之间存在语法上的歧义:
In Ruby, because methods can be called without an explicit receiver and without parentheses, there is a syntactic ambiguity between a local variable reference and a receiverless argumentless method call:
foo
可以 表示没有参数的self
上的调用方法foo
"或取消引用局部变量foo
".
could either mean "call method foo
on self
with no arguments" or "dereference local variable foo
".
如果范围内存在局部变量foo
,则始终将其解释为局部变量取消引用,从不解释为方法调用.
If there exists a local variable foo
in scope, this is always interpreted as a local variable dereference, never as a method call.
那么,局部变量在范围内"是什么意思?这是在解析时间语法上 确定的,在运行时是 not 语义确定的.这个非常重要!局部变量是在解析时定义的:如果解析器看到了对局部变量的分配,则该局部变量将从此刻起进入作用域.但是,只有在运行时进行了初始化,没有对正在进行的代码进行编译时评估:
So, what does it mean for a local variable to "be in scope"? This is determined syntactically at parse time, not semantically at runtime. This is very important! Local variables are defined at parse time: if an assignment to a local variable is seen by the parser, the local variable is in scope from that point on. It is, however, only initialized at runtime, there is no compile time evaluation of code going on:
if false
foo = 42 # from this point on, the local variable foo is in scope
end
foo # evaluates to nil, since it is declared but not initialized
为什么局部变量阴影化"方法而不是绕开方法有意义?好吧,如果方法确实遮盖了局部变量,则将不再有取消引用这些局部变量的方法.但是,如果局部变量遮盖了方法,那么仍然有一种方法可以调用这些方法:请记住,仅对于无接收器的无参数方法调用存在歧义,如果添加显式接收器或显式参数列表,仍可以调用该方法:
Why does it make sense for local variables to "shadow" methods and not the way around? Well, if methods did shadow local variables, there would no longer be a way to dereference those local variables. However, if local variables shadow methods, then there is still a way to call those methods: remember, the ambiguity only exists for receiverless argumentless methods calls, if you add an explicit receiver or an explicit argument list, you can still call the method:
def bar; 'Hello from method' end; public :bar
bar # => 'Hello from method'
bar = 'You will never see this' if false
bar # => nil
bar = 'Hello from local variable'
bar # => 'Hello from local variable'
bar() # => 'Hello from method'
self.bar # => 'Hello from method'
这篇关于解释为局部变量会覆盖方法名称吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!