LoginSignup
8
3

More than 5 years have passed since last update.

Rubyの変数初期化で驚いた話

Last updated at Posted at 2015-06-27

概要

まず、以下のコードを見てください

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で初期化されるのか?
正直まだよくわかってないですが、以下のコードでhogeNameErrorにならないのと同じ理由っぽい?

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の実行時に実際に値を入れるからこのような挙動になるとのこと

8
3
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
3