Clojure + Proce55ing

話題の Clojure(http://clojure.org/)。 id:g000001 さん(http://cadr.g.hatena.ne.jp/g000001/)がとても詳しい。

Clojure って JVM で動くんだよなぁ、ってことは Java のライブラリも呼べるよなぁ、そうすると Proce55ing も呼べるなぁ、そうするとhttp://d.hatena.ne.jp/cranebird/20080906 で書いた、

Common Lisp + jython + PApplet の環境

が作れるかもなぁ、とやってみたら、あっさりできた。ClojureCommon Lisp でもないし Scheme でもないのでまだ全然慣れていないけど。

以下では、

  • CLASSPATH に processing の pde.jar, core.jar を追加して clojure の Repl を起動
  • PApplet, PDrawEventListener, Frame を import
  • 関数定義(※動的にReplで行ってもOK)。 Frame に PApplet のインスタンスを追加して表示する。ただしこの時点では PApplet は空っぽなので何も描かない。
  • PDrawEventListener を定義してランダムに線を描かせてみる。ここでは clojure の proxy によって動的に PDrawEventListener を定義している。
  • 上の動的な機能は jython と同様。ただし微妙な違いとして、jython では = でイベントリスナーを登録できた(内部では reflection を使用)が、 clojure ではもっと java っぽい。まだ見ていないだけかもしれない。
~/clojure_20080916 $ java -classpath $CLASSPATH:./clojure.jar clojure.lang.Repl
Clojure
user=> (import '(processing.core PApplet PDrawEventListener)
	'(java.awt Frame))
nil
user=> (defn p5 []
  (let [p (new PApplet)
	f (new Frame)]
    (. f setSize 300 300)
    (. p (addPDrawEventListener
	  (proxy [PDrawEventListener] []
		 (doDraw [evt]
			 (let [w (. p width)
			       h (. p height)]
			 (. p line (. p random w) (. p random h) (. p random w) (. p random h)))))))
    (. f add p)
    (. p init)
    (. f setVisible true)
    f))
#'user/p5
user=> 
(p5)
java.awt.Frame[frame0,0,22,300x300,layout=java.awt.BorderLayout,title=,resizable,normal]

なお、上記 PApplet は自作のパッチ(http://processing.org/discourse/yabb_beta/YaBB.cgi?board=Integrate;action=display;num=1220794099)を当ててあるけど本質ではない。(残念ながら芳しい反応は無かったが、、、)

ClojureJVM 上で動くということは膨大な Java 資産が使える、ということを実感。いままで「ふうがわりな Lisp 方言だな」くらいに思っていてあまり気にしていなかったけど、これは強力。ABCL(Armed Bear Common Lisp) もいつか試そうと思っていたけど、 Clojure の方が活気がありそうだなぁ。