こんにちは、エンジニアブログ編集部の久保田です。
もうすっかり年末ですね。
年末ということもあって、RubyKaigiがあったり、2.3.0-previewがでたり、Ruby界隈がもりあがっています。
僕も、2.3.0から導入される話題のぼっちオペレーターを早く使いまくりたいです。
ということで今回はRubyについて取り上げたいと思います。
今回は、「スコープ」についてです。
突然ですが、以下のプログラム、もし引数にFixnum以外が来たら、どうなるでしょう?
これ、
p result
がエラーになりそうですが、結果はnilが出力されます。
rubyでは宣言していない変数名やメソッド名を使おうとすると、
NameError: undefined local variable or method `hoge' for main:Object
このようなエラーが出るはずです。
しかし上のプログラムでは、エラーではなく、resultが値なし、という評価になっています。
メソッドミッシングをオーバーライドしているわけではありません。
とても気持ち悪いですね。
なんとなく本能的に、通らなかったifの中の変数はエラーになってほしいものですが。。。
実は、Rubyでは、ifにスコープはつかないんです。
Rubyがスコープを新しく切り替えるタイミングは、class,module,defの宣言が行われた時になります。(スコープゲート)
この決まりはとても厳しく、もし入れ子になっていたとしても、下の階層から変数を使用することはできません。他のスコープのことは全く知ることができないんです。
つまり、以下のプログラムは、A::B.bも、A::B.cもエラーになります。
入れ子であってもスコープが違うと別の領域として認識するのに、ifやwhileのスコープになりそうなところでならない。。。
慣れないと気持ちが悪いですね。
もちろん、ブロックはクロージャーとして使えるので、ブロック内の変数は外にでていったりすることなく、同じスコープ内の変数やメソッドは使うことができます。
すごく基本的なことですが、言語によって違いがでてくるところなので、適切に使ってあげたいですね。
今回はこんなところで。
では、みなさま、良いお年を!