2012-06-10 19 views
5

Il codice seguente funziona in linguaggio comune, ma in emacs lisp, si lamenta "(errore" Tipo di classe sconosciuto orc nei parametri del metodo ")". Perché e come posso risolverlo in emacs lisp? Grazie.Differenza di struttura tra common lisp ed emacs lisp

(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")) 

risposta

3

La cosa è ... defmethod ha bisogno che sia una classe, non una struttura, le strutture in eLisp sono solo vettori. Forse potresti inventare il tuo metodo di invio generico, ma probabilmente il solo utilizzo di classi anziché di strutture lo risolverà - le classi sono implementate in eieio.el, quindi puoi guardare all'interno di esso e vedere come fanno il dispacciamento. Oppure si potrebbe semplicemente avere qualcosa di simile:

(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")))) 

Sarebbe davvero dipenderà da quante classi di creature sono lì, probabilmente si potrebbe trovare un qualche macro che nasconde la condizione o meglio restituisce la funzione da chiamare sulla base di il tipo di tag, ecc.

Di seguito è un'idea semplificata per creare i propri generici, nel caso in cui si desideri attenersi alle strutture e non si richiede molta funzionalità o si è felici di implementarlo da soli:

(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" 
+0

Grazie, controllerò defclass. – louxiu