Perl でも JavaScript っぽくクロージャが作れるんですね
JavaScript ではよくある、こういう書き方。
一応説明すると、これは実行時に外側の無名関数を実行します。外側の無名関数は返り値として、内側の無名関数を返し、変数 counter には内側の無名関数が代入されます。
これの何が嬉しいのか。
- counter 関数が内部に持っている変数 i は隠蔽されており、外から変更できない。
- グローバル空間の汚染は counter 1 つだけ。
といったところでしょうか。とにかく、 JavaScript 脳の人はこういう感じのコードをよく書いている気がします。 JavaScript にはオブジェクト指向によくある protected や private といったアクセスレベルを制御する機能が無いため、これの応用で内部の変数やメソッドを隠蔽することが多いです。 Prototype や jQuery でもそういった使い方がされています。
このように、 JavaScript では無名関数の中にスコープを閉じ込めることができ、これをクロージャと呼びます。
で、最近久しぶりに勉強している Perl 。 Plack のコードを読んでいる中で、 Perl にも無名関数とクロージャがあるということを知ったので、試してみました。
上部のおまじない的なものを除けば、やってることは本質的に何も変わりません。
ついでに Ruby も。これもやっていることは特に変わらないと思います。
Python にも無名関数 (ラムダ) はあるので、同じようなことができそうな気がしたのですが、うまくいかず、代わりにこんな書き方に。
これはクロージャではなく、ジェネレータという機能を使っています。内部の変数が隠蔽されており、名前空間の汚染も 1 つだけですが、最初は関数だった counter にジェネレータをぶち込むというのは、お行儀的にはよくないかもしれません。
で、 PHP でも 5.3 からは無名関数・クロージャが使えるようになったので、試してみたのですが、以下の JavaScript 的な記述では parse error となりました ...
以下のように書き換えると動きますが、これでは名前空間の汚染が 2 つです。
そして、何かもう方向を見失っている例。
変数の名前空間汚染は 1 つだけど、クラス名の名前空間まで汚染してしまっている上、返り値が文字列になっています。 (__toString はそのように定義しないといけないため)
そして、一応数値を返すようにしたものが以下。
なんか、 JavaScript と Perl の話だったはずが、暗に PHP を Dis る結果になってしまったので、今日はこの辺で。