概要
まず、以下のコードを見てください
irb(main):001:0> hoge
結果はなんでしょうか?
NameErrorですね。当然ですね
NameError: undefined local variable or method `hoge' for main:Object
from (irb):1
from /Users/itkrt2y/.rbenv/versions/2.2.2/bin/irb:11:in `<main>'
では、次に以下のようにしてみましょう
irb(main):002:0> if false
irb(main):003:1> foo = true
irb(main):004:1> end
=> nil
irb(main):005:0> foo
002~004は条件式でくくっていますが、見ての通りif falseなので内部は実行されません。
では、005のfooの結果はどうなるでしょうか?
NameErrorだと思いました?
僕はそう思ってました
だが、結果は違った......!!
irb(main):005:0> foo
=> nil
答えは NameErrorではなくnil!
じゃ、じゃあcaseではどうなんだ!?
irb(main):006:0> case :a
irb(main):007:1> when :b
irb(main):008:1> bar = true
irb(main):009:1> end
=> nil
irb(main):010:0> bar
=> nil
これもnil!
実行されないはずなのになぜnilで初期化されるのか?
正直まだよくわかってないですが、以下のコードでhogeがNameErrorにならないのと同じ理由っぽい?
hoge ||= "default" # hoge = hoge || "default"
ちなみに
当たり前ですが、初期化済みの場合はnilで上書かれたりはしません
irb(main):001:0> hoge = "hey!"
=> "hey!"
irb(main):002:0> if false
irb(main):003:1> hoge = "hello"
irb(main):004:1> end
=> nil
irb(main):005:0> hoge
=> "hey!"
まとめ
条件式にて実行されない処理内の変数も初期化されます
追記
どうやらこれはvariable hoistingっていうらしい。
http://rubylogs.com/variable-hoisting-ruby/
parserが条件式の結果はどうであるかは御構い無しにまず一度全ての変数のメモリー領域を確保し、
interpreterの実行時に実際に値を入れるからこのような挙動になるとのこと