2012-06-10 3 views
5

Der folgende Code funktioniert in gemeinsamen Lisp, aber in Emacs lisp, klagt es "(Fehler" Unbekannter Klassentyp orc in Methodenparameter ")". Warum und wie kann ich es in Emacs Lisp beheben? Vielen Dank.Struct Unterschied zwischen gemeinsamen Lisp und 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")) 

Antwort

3

Das Ding ist ... defmethod muss es eine Klasse sein, nicht eine Struktur, Strukturen in eLisp sind nur Vektoren. Vielleicht könnten Sie Ihre eigene generische Dispatch-Methode entwickeln, aber wahrscheinlich werden nur Klassen anstelle von Strukturen verwendet - Klassen werden in eieio.el implementiert, so dass Sie sich das Innere ansehen und sehen können, wie sie versenden. Oder Sie könnten es einfach so etwas wie:

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

Es wäre wirklich davon abhängen, wie viele Klassen von Kreaturen sind, wahrscheinlich könnten Sie mit etwas Makro kommen, die die Bedingung versteckt oder vielmehr gibt die Funktion aufzurufen, basierend auf Der Typ-Tag usw.

Unten finden Sie eine vereinfachte Idee für die Erstellung Ihrer eigenen Generika, nur für den Fall, dass Sie bei den Strukturen bleiben möchten und nicht viel Funktionalität benötigen oder diese selbst implementieren:

(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

Danke, ich werde defclass überprüfen. – louxiu