事は... 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"