事がある... 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"
ありがとうございます、私はdefclassをチェックします。 – louxiu