スコープ
スコープとは
スコープは範囲、またはエリアなどで定義できる。つまり、プログラミングでのスコープはどこまで参照できるかを決める範囲を指してスコープと呼ぶ。
スコープの変更
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
にもブロックが渡せる