事情是... 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