From: LeonardoBizzoni Date: Wed, 10 Jan 2024 14:38:11 +0000 (+0100) Subject: Documentazione creazione dei metodi X-Git-Url: http://git.leonardobizzoni.com/?a=commitdiff_plain;h=3e62df1b0539d3b43b40f703e416cd7b8cc01b04;p=ObjectOriented-Prolog-Lisp Documentazione creazione dei metodi --- diff --git a/Lisp/README.org b/Lisp/README.org index 6fd05ab..50f8ccd 100644 --- a/Lisp/README.org +++ b/Lisp/README.org @@ -280,7 +280,27 @@ di 2 classi, il che tornerà utile nel controllo dei tipi. #+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) @@ -297,7 +317,7 @@ di 2 classi, il che tornerà utile nel controllo dei tipi. (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)) @@ -307,7 +327,7 @@ di 2 classi, il che tornerà utile nel controllo dei tipi. ((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 diff --git a/Lisp/ool.lisp b/Lisp/ool.lisp index 381de6f..45377ca 100644 --- a/Lisp/ool.lisp +++ b/Lisp/ool.lisp @@ -43,6 +43,16 @@ ((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) @@ -136,7 +146,7 @@ (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)) @@ -146,7 +156,7 @@ ((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