JavaScriptの頻出テクニックにして、それ以外の言語でも基礎教養的な雰囲気のある クロージャとスコープですが、なんとなく小難しそうな雰囲気をまとっていたりするせいか いまいち浸透していないので簡単にまとめようと思いました。
用語の細かい定義とかはかなりいい加減なので、気になった人は別途wikipediaとか参照するといいと思います。
レキシカルスコープとは
高階関数という言葉をご存知でしょうか。簡単に説明すると、関数を返す関数や、関数を引数にとる関数のことです。
Cでいうところの関数ポインタに似たアトモスフィアを持っています。
レキシカルスコープを採用している言語(つまり現代のほとんどの言語)は、この高階関数 を使う時に、上のスコープの変数を参照して、それを束縛することが出来ます。
こんな説明だけでは、正直なんのこっちゃという感じだと思うのでコードで示したいと思います。
def closure_test(val): """ >>> is_hoge = closure_test("hoge") >>> is_four = closure_test(4) >>> is_hoge("hoge") True >>> is_four(4) True >>> is_hoge("bar") False >>> is_four("foo") False """ def __is_x(x): return x == val return __is_x # 上は以下のコードと等価 #return lambda x: x == val
closure_test関数は内部関数である__is_x
関数を返り値に持つ関数ですが、ここでまず
注目したいところは__is_x関数が、自分より上のスコープに存在するval
という変数を
使っていることです。
そして、ここで一番大事なのは、is_hogeに束縛されている__is_x
と、is_fourに束縛
されている__is_x
がそれぞれ内部で参照している変数valは、独立して存在していることです。
上のスコープの関数が持つ変数を参照して、またその関数が終了しても束縛し続けることが
出来る、つまり関数を定義した時の変数を束縛して持ち運べる特性をレキシカルスコープ
(静的スコープ)と言います。
そして、その静的なスコープを保持したまま外部に渡される内部関数をクロージャといいます。
多分。
まとめ
先にあげたコード例を見てもわかる通り、クロージャは説明しにくいだけで、使う分には
実際易しい概念です。
どうしてもわからん人は、クラスに見立てて理解するといいと思います。
クラスは、インスタンスごとに異なる状態を持ち運ぶことが出来ますよね? それと大体
同じよーなことが出来るとかそういう感じの理解でいいんじゃないんですかね。
上のコードが理解できたら、部分適用でググって、それを自分で実装しなおしたりするといい感じに練習になると思います。
おしまい