Born Too Late

Yuya's old tech blog.

Perl でも JavaScript っぽくクロージャが作れるんですね

2010-10-17 16:29:53

JavaScript ではよくある、こういう書き方。

一応説明すると、これは実行時に外側の無名関数を実行します。外側の無名関数は返り値として、内側の無名関数を返し、変数 counter には内側の無名関数が代入されます。

これの何が嬉しいのか。

といったところでしょうか。とにかく、 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 る結果になってしまったので、今日はこの辺で。