Rubyのスコープのお話

こんにちは、エンジニアブログ編集部の久保田です。

もうすっかり年末ですね。  
年末ということもあって、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のスコープになりそうなところでならない。。。

慣れないと気持ちが悪いですね。


もちろん、ブロックはクロージャーとして使えるので、ブロック内の変数は外にでていったりすることなく、同じスコープ内の変数やメソッドは使うことができます。


すごく基本的なことですが、言語によって違いがでてくるところなので、適切に使ってあげたいですね。


今回はこんなところで。


では、みなさま、良いお年を!