bar
が定義されているかどうかに違いはありません。どちらの場合も、bar
本体では未定義です。ただし、後者の場合、body は評価されないため、問題ありません。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
に実行されるため、本体で定義されると想定されます。しかし、そうではありません。本体が最初に解析されたため、これがメソッドなのか変数ノードなのか、代入が見られる前に構文ツリーに挿入されたのかわからないからです。
ただし、そのノードが解釈されない場合、つまり条件が false の場合は、悪いことは何も起こりません。