スコープ
スコープとは
スコープは範囲、またはエリアなどで定義できる。つまり、プログラミングでのスコープはどこまで参照できるかを決める範囲を指してスコープと呼ぶ。
スコープの変更
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
このスコープの移動を追っていると、
まず、v1が定義されたトップレベルのスコープだ。次に、MyClassが定義されたスコープだ。
Rubyの「内部スコープ」から「外部スコープ」を参照する「入れ子構造」が存在しないため、スコープはきちんと区別されている。新しいスコープに入ると、束縛も新しい束縛と交換される。なので、my_methodが呼び出されるとさらに新しいスコープがオープンされて終わったらスコープは削除され、トップレベルのスコープに戻る。そこでまたmy_methodを呼び出すと新しいスコープをオープンして、新しいv3を定義する。(ここで定義されたv3は先のv3とは関係ない)
スコープゲート
プログラムがスコープを切り替えて、新しいスコープをオープンする場所は3つある。
- クラス定義(class)
- モジュール定義(module)
- メソッド呼び出し(def)
スコープのフラット化
1 2 3 4 5 6 7 8 9 | |
このコードでクラスとメソッドでトップレベルのロカール変数のmy_varを使いたい場合、どうすればいいのか。今までの説明だったらスコープがそれぞれ違くて使えないけど。
さっき言った通り、スコープゲートは3つがある。
つまり、スコープゲート以外にはスコープ関係なくトップレベルのローカル変数を使えるということになるのだ。
class、defの代わりにClass.new、define_methodを使えばクロージャでmy_varを取得できる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
こういうふうに書くと、無事出力される。
気になる点
そうしたらdefine_methodにブロックを渡したらどうなるだろう。
1 2 3 4 5 6 | |
エラーになる。
1 2 3 4 5 6 7 | |
defでメソッドを定義する時は問題なく動く。
define_methodでブロックが使える方法とは何があるのかな。
1 2 3 4 5 | |
1 2 3 4 5 | |
lambdaとprocを使うとdefine_methodにブロックを渡せる。
まとめ
- どこまで参照できるかを決める範囲をスコープと呼ぶ
- スコープはきちんと区別されている。新しいスコープに入ると、束縛も新しい束縛と交換される
- スコープゲートは3つがある
- クラス定義(class)
- モジュール定義(module)
- メソッド呼び出し(def)
class、defの代わりにClass.new、define_methodを使えばスコープのフラット化ができるdefine_methodにもブロックが渡せる