C++ と CLOS
C++ のプログラムを、勉強として CLOS に書き換えている。C++ も CLOS も両方勉強しているから当たり前だが、これがなかなか難しい。
今のところ、素朴に C++ のクラス定義をそのまま CLOS のクラスに変換しているが、以下のような違和感を感じている。
- CLOS ではメソッドがクラスに属するわけではないので、C++ のメソッドを Common Lisp の defmethod で書くと毎回 this 相当のインスタンスを引数に渡すことになり、コードが煩雑。Python っぽい。
- C++ の基本クラス(String クラスなど)はなかなか充実しているが、CLOS には相当するものがない。正確には存在するがより低レベルなものしか無い感じ。
- メソッド名。CLOS の仮引数リストは固定的なので、C++ のクラスで使える length のような言語の組み込み関数と同じメソッド名が使いにくい。(使いにくい、と書いたのは、方法がちゃんとあるはずだから。調査不足。)
- C++ で書かれたよいクラスは、 CLOS に焼き直すととても lisp っぽくない副作用だらけのコードになる、気がする。
- C++ っぽく書いた下手な lisp コードは、全部書き上がらないとテストできない。もっと小さい単位でテストできるようにすると、やっぱり C++ っぽく書くだけではだめで、ほとんど全部、 lisp らしく書き換えなくてはならないかもしれない。
もうしばらく手を動かしてみよう。
追記
Peter Seibel "Practical Common Lisp", Chapter 21 にきちんと説明があった。独自パッケージ :foobar で :common-lisp パッケージを use していて、かつ、length というメソッドを作りたい場合は以下のようにする。
;; -*- mode: common-lisp; package: foobar; -*- (defpackage :foobar (:use :common-lisp) (:shadow :length) ) (in-package :foobar) (defclass seq () ((data :accessor seq-data :initform nil :initarg :data))) (defmethod length ((seq seq)) (cl:length (seq-data seq)))
shadow によって、 :foobar パッケージの length が定義できるようになった。代わりに、 :common-lisp パッケージの length を参照するのが若干煩雑になっている。当たり前といえば当たり前だが、若干不便。
はてなの d:id:sumin (オブジェクト指向についてためになる)氏の記事も参考になった。
- http://d.hatena.ne.jp/sumim/20070426/p1 CLOS のパッケージを用いたメソッドコンフリクトへの対処を試みる