2012-06-10 9 views
5

El código siguiente funciona en lisp común, pero en emacs lisp, se queja "(error" Clase de clase desconocida orc en parámetros de método ")". ¿Por qué y cómo puedo solucionarlo en emacs lisp? Gracias.Diferencia de estructura entre lisp común y 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")) 

Respuesta

3

La cosa es que ... defmethod necesita que sea una clase, no una estructura, estructuras en elisp son vectores. Tal vez podría idear su propio método de despacho genérico, pero probablemente usar clases en lugar de estructuras lo resolverá: las clases se implementan en eieio.el, por lo que puede ver el interior y ver cómo lo envían. O simplemente podría tener algo como:

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

Sería realmente dependerá del número de clases de criaturas están allí, probablemente usted podría llegar a algún macro que oculta la condición o bien devuelve la función de llamada según la etiqueta de tipo, etc.

A continuación, se presenta una idea simplificada para crear sus propios genéricos, en caso de que quiera seguir con las estructuras y no necesite mucha funcionalidad o si lo hace por su cuenta:

(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

Gracias, comprobaré defclass. – louxiu