2016-10-04 12 views
4

実行時にクラスを作成する必要があります。メタクラスプロトコルが完全に共通Lispで標準化されていないことを知って、The Common Lisp Object System MetaObject Protocolを閲覧した後、私は、クラスを作成し、それをインスタンス化し、その数をインスタンスのスロット値を設定するために、次のコードを試してみました:Common-Lispで実行時にクラスを移植可能にする方法CLOS

(defparameter *my-class* 
    (make-instance 'standard-class 
       :name 'my-class 
       :direct-slots '((:name x :readers (get-x) :writers ((setf get-x)))))) 

(defparameter *my-instance* (make-instance *my-class*)) 

(setf (get-x *my-instance*) 42) ;; => 42 

残念ながら、このコードはSBCLではなく、クラスの作成が動作しているようですCCL、上で正常に動作しますが、次のエラーが発生し(make-instance *my-class*)インスタンスの作成:

There is no applicable method for the generic function: 
    #<STANDARD-GENERIC-FUNCTION INITIALIZE-INSTANCE #x30200002481F> 
when called with arguments: 
    (#<error printing CONS #x302001A9F6A3> 
    [Condition of type CCL:NO-APPLICABLE-METHOD-EXISTS] 

私は非表示にするcloser-mopパッケージ、見てみましたメタのさまざまな実装間の違いオブジェクトプロトコルは、私のスコープに役立つ関数やクラスを見つけることができませんでした。

質問:クラスを作成し、実行時にメタクラスレベルのCLOSを直接使用してインスタンス化するポータブルな方法はありますか?

+0

、あなたは(http://mop.lisp.se/dictionary.html#ensure-class)[確実-クラス]を試みることができる、または[クラス-使用してクラスを確実]( http://mop.lisp.se/dictionary.html#ensure-class-using-class)。 – coredump

+1

直接スーパークラスを指定してもCCLがうまくいくようです:direct-superclasses(list(find-class 'standard-object)) ' – jkiiski

+0

ありがとう@jkiiski、問題は私がスーパークラスを指定したはずです。回答として投稿すると、私はそれを受け入れます。 – Renzo

答えて

3

CCLでは、直接スーパークラスも手動で指定する必要があるようです。

(defparameter *my-class* 
    (make-instance 'standard-class 
       :name 'my-class 
       :direct-slots '((:name x :readers (get-x) :writers ((setf get-x)))) 
       :direct-superclasses (list (find-class 'standard-object)))) 
3

通常、クラスを作成するにはENSURE-CLASSを使用します。 ENSURE-CLASSの目的は、DEFCLASSと機能的に同等でなければなりません。特別な実装固有のものを除いてDEFCLASS - 例えば開発環境の機能をサポートする。

MAKE-INSTANCEを使用できますが、たとえば、その名前でクラスを登録しないことがあります。また、追加のENSURE-CLASS-USING-CLASSメソッドも呼び出されません。

メタクラスのデフォルト値はstandard-classなので、CCLはダイレクトスーパークラスのデフォルト値も計算する必要がありますが、残念なことにそれはありません。

クローズモップは、これらの非互換性を修正することを願っていますが、私はチェックしていません。 CCLで

? (ensure-class 'my-class 
       :direct-slots '((:name x 
           :readers (get-x) 
           :writers ((setf get-x)))) 
       :direct-superclasses (list (find-class 'standard-object))) 
#<STANDARD-CLASS MY-CLASS> 
? (find-class 'my-class) 
#<STANDARD-CLASS MY-CLASS> 
? (let ((foo (make-instance 'my-class))) 
    (setf (get-x foo) 10) 
    (incf (get-x foo) 32) 
    (get-x foo)) 
42 

LispWorksは、実際にそれを正しくありません。メタクラスのデフォルトはstandard-classであり、直接スーパークラスはstandard-objectです。近い-MOPで

CL-USER 25 > (clos:ensure-class 'foobar 
       :direct-slots '((:name x 
            :readers (get-x) 
            :writers ((setf get-x))))) 
#<STANDARD-CLASS FOOBAR 4020001713> 

CL-USER 26 > (class-direct-superclasses *) 
(#<STANDARD-CLASS STANDARD-OBJECT 40E018E313>) 
+0

あなたの完全な答えをありがとう! – Renzo

関連する問題