解释为局部变量会覆盖方法名称吗?

saw*_*awa 5 ruby local-variables self-reference

此问题一样,当在其自己的赋值中使用未定义的局部变量时,将对其进行求值nil.

x = x # => nil 
Run Code Online (Sandbox Code Playgroud)

但是当局部变量的名称与现有方法名称冲突时,它更棘手.为什么下面的最后一个例子会返回nil

{}.instance_eval{a = keys} # => []
{}.instance_eval{keys = self.keys} # => []
{}.instance_eval{keys = keys} # => nil
Run Code Online (Sandbox Code Playgroud)

Jör*_*tag 12

在Ruby中,因为可以在没有显式接收器且没有括号的情况下调用方法,所以在局部变量引用和无接收器无参数方法调用之间存在语法歧义:

foo
Run Code Online (Sandbox Code Playgroud)

可能意味着"call方法fooself不带任何参数"或"取消引用局部变量foo".

如果foo范围中存在局部变量,则始终将其解释为局部变量取消引用,而不是方法调用.

那么,局部变量"在范围内"意味着什么呢?这是确定的语法分析时,没有语义在运行时.这是非常重要的!局部变量在解析时定义:如果解析器看到对局部变量的赋值,则局部变量在此范围内.但是,它仅在运行时初始化,没有编译时间的代码评估:

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
Run Code Online (Sandbox Code Playgroud)

为什么局部变量有"阴影"方法而不是方法呢?好吧,如果方法确实影响了局部变量,那么就不再有一种方法可以取消引用那些局部变量.但是,如果局部变量为阴影方法,那么仍然有一种方法可以调用这些方法:记住,模糊性仅存在于无接收无参数方法调用中,如果添加显式接收器或显式参数列表,您仍然可以调用该方法:

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'
Run Code Online (Sandbox Code Playgroud)