別エントリで実装等について書く前に、これまでの経緯のまとめ。
以前のエントリ で↓のように書いていたのだが、
Scalaライクなミックスイン はエイプリルフールネタです。申し訳ない。
本気で取り組みたいですが、なかなか難しいですね。
求む、フルタイムでやらせてくれるお大尽。
プログラミングをしない人にPHPを少しわかりやすくする関数 “not” #phpadvent2012 に触発されて
よーし、おじさんnot演算子をZend Engineに追加しちゃうぞー / “プログラミングをしない人にPHPを少しわかりやすくする関数 “not” #phpadvent2012 - 頭ん中” htn.to/HaqbQq
— Ryusuke SEKIYAMAさん (@rsky) 12月 14, 2012
と言ってしまい、その流れでphp-srcをforkしてnot演算子を実装したり、until文/unless文を実装したりしているうちに気分がノってきて、Synfomy勉強会で@itemanと話したのが決め手で「もう一度トライしてみよう」と相成った。
そして、寝て起きてPHPのソースコードを見ていたら、なんか出来そうな気がしたので選挙に行ってから作業を始めると、割とあっさりできてしまって我ながらびっくり。難しいと思い込んで敬遠していたのはなんだったのか。
PHPでScala風ミックスインできた!構想8ヶ月半!実装4時間半!github.com/rsky/php-src/c…
— Ryusuke SEKIYAMAさん (@rsky) 12月 16, 2012
構想8ヶ月半というか、着想してから8ヶ月半といった方が正確かも。
gist.github.com/4308375 のように、new A use B, C; とすると、if (!class_exists(‘A+B+C’) { class A+B+C extends A { use B, C } } としたのと等価なクラスとそのインスタンスを生成します
— Ryusuke SEKIYAMAさん (@rsky) 12月 16, 2012
ミックスインの実体は通常はコンパイルできない名前のクラスを作っているだけなので、結果として作成されたクラスのインスタンス化や再ミックスインも可能だった。gist.github.com/4308375
— Ryusuke SEKIYAMAさん (@rsky) 12月 16, 2012
昨日の版のparserだとshift/reduce conflictsで怒られるので複数のtraitsをミックスインするときは new A use (B, C) みたいに括弧で括ることにした。
— Ryusuke SEKIYAMAさん (@rsky) 12月 17, 2012
あとはデシリアライズするときに合成クラスがなかったら元クラスをlookupして合成するぐらいかなー(このへんが面倒くさくなることや、スクリプト側でそこまでできる必要を感じないのでinsteadof文とかはサポートしない)
— Ryusuke SEKIYAMAさん (@rsky) 12月 17, 2012
こうしてできたScala風ミックスインと、以前からやっていたClang Blocks風無名関数にインライン呼出構文を加えたもの、全部入りのQIQブランチも作成。QIQはPHPのアルファベットを一つずつ進めたもので、PHPの次を意味する由緒正しい名前。(僕の中では)
ダウンロード
configure生成済のソースコード一式と、特定環境向けのバイナリを用意したので、気軽に試してみてほしい。
追記:20121220 にはミックスイン済クラスの再利用に関するバグがあったので修正版の 20121221 と差し換え
- Source (gzip) qiq-5.6.0-20121221.tar.gz
- Source (bzip2) qiq-5.6.0-20121221.tar.bz2
- Source (xz) qiq-5.6.0-20121221.tar.xz
- Binary (Debian 6) qiq-5.6.0-20121221-debian6-amd64.tar.bz2
- Binary (Ubuntu 12.04.1 LTS) qiq-5.6.0-20121221-ubuntu1204-amd64.tar.bz2
- Binary (CentOS 6) qiq-5.6.0-20121221-centos6-x86_64.tar.bz2
- Binary (Mac OS X) qiq-5.6.0-20121221-macosx.tar.bz2