#+end_src
*** Creazione di metodi
-
+Predicato utilizzato per define i metodi di una classe.
+La definizione di un metodo viene effettuata tramite la creazione di una
+funzione "metodo" il cui nome corrisponde al nome del metodo da creare,
+prende degli argomenti in ingresso capitanati dall'istanza su cui chiamare
+il metodo.
+Nel corpo di questa funzione inizialmente vengono svolti dei controlli
+per verificare che il primo argomento sia effettivamente un'istanza di una
+classe che implementi il metodo chiamato e successivamente viene chiamto
+il vero corpo del metodo (/definito precedentemente/).
+
+Il problema principale da superare è il fatto che più classi possono
+implementare un metodo con lo stesso nome e con argomenti diversi.
+Per risolvere questo problema permettiamo alla funzione "metodo" di
+ricevere un numero variabile di argomenti tramite la keyword /&rest/.
+Recuperiamo il corpo del metodo da eseguire dall'istanza /this,/ creiamo
+ed eseguiamo a runtime una lambda con argomenti l'istanza e gli argomenti
+definiti all'interno del metodo nella lista rappresentante l'istanza ed il
+corpo della lambda è il corpo del metodo da eseguire.
+
+In questo modo possiamo ricevere un numero variabile di argomenti ed
+eseguire codice in base all'istanza che viene data alla funzione.
#+begin_src lisp :tangle ool.lisp
(defun define-methods (methods)
(unless (get-method (getf this :methods) (first method))
(error "~A non ha un metodo ~A"
(getf this :classname) (first method)))
- (apply (get-method-body this (first method))
+ (apply (build-method-body this (first method))
(append (list this) args)))))
methods))
((eq (caar methods) name) (car methods))
(t (get-method (cdr methods) name))))
-(defun get-method-body (this method-name)
+(defun build-method-body (this method-name)
(eval
(append
(list 'lambda
((eq (caar fields) field-name) (cadar fields))
(t (field-helper (cdr fields) field-name))))
+(defun field* (instance &rest fields)
+ (if (null fields)
+ (error "La lista di fields non può essere vuota")
+ (field*-helper instance fields)))
+
+(defun field*-helper (instance fields)
+ (if (null (cdr fields))
+ (field instance (car fields))
+ (field*-helper (field instance (car fields)) (cdr fields))))
+
(defparameter *classes-specs* (make-hash-table))
(defun add-class-spec (name class-spec)
(unless (get-method (getf this :methods) (first method))
(error "~A non ha un metodo ~A"
(getf this :classname) (first method)))
- (apply (get-method-body this (first method))
+ (apply (build-method-body this (first method))
(append (list this) args)))))
methods))
((eq (caar methods) name) (car methods))
(t (get-method (cdr methods) name))))
-(defun get-method-body (this method-name)
+(defun build-method-body (this method-name)
(eval
(append
(list 'lambda