5

以下のコードはcommonlispで機能しますが、emacs lispでは「(エラー "メソッドパラメータの不明なクラスタイプorc")」と文句を言います。なぜそしてどうすればemacslispで修正できますか?ありがとう。

(defun randval (n)
  (1+ (random (max 1 n))))

(defstruct monster (health (randval 10)))

(defstruct (orc (:include monster)) (club-level (randval 8)))

(defmethod monster-show ((m orc))
  (princ "A wicked orc with a level ")
  (princ (orc-club-level m))
  (princ " club"))
4

1 に答える 1

2

事は... defmethod はそれが構造体ではなくクラスである必要があります.eLispの構造体は単なるベクトルです. 独自のジェネリック ディスパッチ メソッドを考え出すこともできますが、構造体の代わりにクラスを使用するだけで解決する可能性があります。クラスは eieio.el で実装されているため、その内部を見て、ディスパッチがどのように行われるかを確認できます。または、単に次のようにすることもできます。

(defun foo (monster)
  (cond
    ((eql (aref monster 0) 'cl-orc-struct) ...) ; this is an orc
    ((eql (aref mosnter 0) 'cl-elf-struct) ...) ; this is an elf
    (t (error "Not a mythological creature"))))

クリーチャーのクラスがいくつあるかによって異なります。おそらく、条件を非表示にしたり、タイプタグなどに基づいて呼び出す関数を返すマクロを考え出すことができます。

以下は、独自のジェネリックを作成するための単純化されたアイデアです。構造体に固執したい場合や、多くの機能を必要としない場合、または独自に実装しても問題ない場合に備えて:

(defvar *struct-dispatch-table* (make-hash-table))

(defun store-stuct-method (tag method definition)
  (let ((sub-hash
     (or (gethash method *struct-dispatch-table*)
         (setf (gethash method *struct-dispatch-table*)
           (make-hash-table)))))
    (setf (gethash tag sub-hash) definition)))

(defun retrieve-struct-method (tag method)
  (gethash tag (gethash method *struct-dispatch-table*)))

(defmacro define-struct-generic (tag name arguments)
  (let ((argvals (cons (caar arguments) (cdr arguments))))
    `(defun ,name ,argvals
       (funcall (retrieve-struct-method ',tag ',name) ,@argvals))))

(defmacro define-struct-method (name arguments &rest body)
  (let* ((tag (cadar arguments))
     (argvals (cons (caar arguments) (cdr arguments)))
     (generic))
    (if (fboundp name) (setq generic name)
      (setq generic 
        `(define-struct-generic 
          ,tag ,name ,arguments)))
    (store-stuct-method 
     tag name 
     `(lambda ,argvals ,@body)) generic))

(define-struct-method test-method ((a b) c d)
  (message "%s, %d" a (+ c d)))

(test-method 'b 2 3)
"b, 5"
于 2012-06-10T12:33:05.127 に答える