Rubyでは、メソッドは明示的なレシーバーや括弧なしで呼び出すことができるため、ローカル変数参照とレシーバーのない引数のないメソッド呼び出しの間には構文上のあいまいさがあります。
foo
「引数なしでメソッドを呼び出す」または「ローカル変数を逆参照する」のいずれかを意味する可能性があります。foo
self
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
ローカル変数がメソッドを「シャドウ」するのが理にかなっているのはなぜですか?メソッドがローカル変数をシャドウイングした場合、それらのローカル変数を逆参照する方法はなくなります。ただし、ローカル変数がメソッドをシャドウする場合でも、これらのメソッドを呼び出す方法があります。あいまいさは、レシーバーのない引数のないメソッド呼び出しにのみ存在します。明示的なレシーバーまたは明示的な引数リストを追加した場合でも、メソッドを呼び出すことができます。
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'