概要
まず、以下のコードを見てください
irb
irb(main):001:0> hoge
結果はなんでしょうか?
NameError
ですね。当然ですね
irb
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
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
irb(main):005:0> foo
=> nil
答えは NameError
ではなくnil
!
じゃ、じゃあcase
ではどうなんだ!?
irb
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
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の実行時に実際に値を入れるからこのような挙動になるとのこと