From: LeonardoBizzoni Date: Thu, 11 Jan 2024 13:06:03 +0000 (+0100) Subject: Finita documentazione lisp X-Git-Url: http://git.leonardobizzoni.com/?a=commitdiff_plain;h=22fa83f2645b5ea6a8f3808e138b509966ab618f;p=ObjectOriented-Prolog-Lisp Finita documentazione lisp --- diff --git a/Lisp/README.org b/Lisp/README.org index fdb0e4f..6c6779f 100644 --- a/Lisp/README.org +++ b/Lisp/README.org @@ -1,4 +1,4 @@ -#+title: 🔥 OOΛ in Common Lisp 🔥 +#+title: OOΛ in Common Lisp #+author: Bizzoni Leonardo (899629) #+author: Kier Mirko Tolentino(899728) @@ -72,7 +72,9 @@ tra il nome della classe e la lista ottenuta. (format "Sum: ~D~%" (+ number (field this 'foo)))))) (def-class 'bar nil - '(fields (bar "42")) + '(fields + (bar "42" string) + (baz nil foo)) '(methods (foo () (format "Favourite number is ~D~%" field(this 'bar))))) @@ -104,7 +106,7 @@ predicati di controllo seguenti. *** Esempio pratico #+begin_src lisp (defparameter f (make 'foo)) -(defparameter b (make 'bar 'bar "42")) +(defparameter b (make 'bar 'bar "Ciao mondo!" 'baz f)) #+end_src ** field @@ -168,7 +170,7 @@ Questo predicato e la seguente clausola sono equivalenti. *** Esempio pratico #+begin_src lisp -(field* foobar 'a 'b 'c) +(field* b 'baz 'foo) ;; 42 #+end_src @@ -348,7 +350,14 @@ eseguire codice in base all'istanza che viene data alla funzione. #+end_src ** Creazione di un'istanza +La creazione di un'istanza data la rappresentazione in forma di lista di +una classe è una banale modifica al valore della keyword /:type/ in /'object/. +Durante la creazione di un'istanza è anche possibile passare una sequenza +di /'fieldname new-value/ per modificare il valore di default di uno più +field. +Naturalmente se si cerca di "assegnare" un valore ad un field *non* presente +nella definizione della classe questo provocherà un errore. #+begin_src lisp :tangle ool.lisp (defun create-instance (listclass new-fields) @@ -368,18 +377,11 @@ eseguire codice in base all'istanza che viene data alla funzione. (first new-fields) ;; nome del field (second new-fields)) ;; nuovo valore (cdr (cdr new-fields))))) -#+end_src - -*** Impostare i campi dell'istanza - -#+begin_src lisp :tangle ool.lisp (defun set-instance-field (instance name value) - ;; `setf` modifica in-place (setf (getf instance :fields) (set-field (getf instance :fields) name value)) - ;; quindi serve resistuire `instance` instance) (defun set-field (fields name value) @@ -392,7 +394,13 @@ eseguire codice in base all'istanza che viene data alla funzione. #+end_src ** Stabilire se un simbolo è una classe +Per stabilire se il simbolo /name/ dato rappresenta una classe basta +cercare all'interno dell'hash-table il nome e, se presente, verificare +che il valore della keyword /:type/ all'interno della rappresentazione in +forma di lista della classe sia il simbolo /'class/. +/Vedi [[*Creazione della classe in formato lista][creazione di una classe]] per maggiori informazioni sulla +struttura di una classe./ #+begin_src lisp :tangle ool.lisp (defun is-class (name) @@ -401,8 +409,19 @@ eseguire codice in base all'istanza che viene data alla funzione. nil)) #+end_src -** Controlla se il simbolo passato è un'instance della classe +** Stabilire se un simbolo è un'istanza +Il conportamente di questo predicato varia in base agli argomenti +che gli vengono dati. + +Se viene dato solo un argomento allora il predicato deve stabilire se +l'argomento /instance/ è un'istanza di una generica classe. +Per essere un'istanza, /instance/ deve essere una lista ed avere +/'object/ come valore della keyword /:type/. +Se invece viene dato anche un nome rappresentante una classe, allora +il predicato deve verificare che /instance/ non sia solo una generica istanza +ma anche un'istanza della classe /class-name/ o un'istanza di una sua +classe figlia. #+begin_src lisp :tangle ool.lisp (defun is-instance (instance &optional (class-name t)) @@ -411,14 +430,44 @@ eseguire codice in base all'istanza che viene data alla funzione. (and (listp instance) (eq (getf instance :type) 'object))) - (and (listp instance) - (or (eq (getf instance :classname) class-name) - (member class-name (getf instance :parents))) - (eq (getf instance :type) 'object)))) + (or + (null instance) + (and (listp instance) + (or (eq (getf instance :classname) class-name) + (member class-name (getf instance :parents))) + (eq (getf instance :type) 'object))))) #+end_src +Inoltre, per semplificare l'utilizzo di una classe come tipo di un /field/, +si assume che /nil/ sia un'istanza di qualunque classe. + ** Controllo tipo valore +Il controllo dei tipi si divide un 2 parti: +- controllo di un valore dato un field +- controllo di un valore dato un tipo +Il primo caso viene utilizzato principalmente durante la creazione di +un'istanza per verificare, se presenti degli "assegnamenti", che i valori +siano del tipo indicato dal field della classe. + +#+begin_src lisp :tangle ool.lisp +(defun type-check-field (field value) + (if (eq (length field) 2) + t + (type-check value (third field)))) +#+end_src + +Il secondo caso viene utilizzato principalmente durante la creazione di +una classe principalmente per controllare che tutti i field definiti siano +del tipo corretto. +In particolare, dato che un field può essere sia una tupla /(name value)/ che +una tripla /(name value type)/, nel caso in cui /field/ non sia dotato di un +tipo non si ha la necessità di effettuare alcun controllo +su di esso, il /field/ avrà quindi un tipo /dinamico/. +Viceversa se il /field/ è dotato di tipo, esso potrà essere: +- un tipo implementato da lisp, dove il controllo del tipo del valore + viene svolta dalla funzione nativa /typep/ +- una classe, dove il valore deve essere un'istanza della classe stessa #+begin_src lisp :tangle ool.lisp (defun validate-fields-type (fields) @@ -441,11 +490,6 @@ eseguire codice in base all'istanza che viene data alla funzione. "o è una terna (name value type)" "o una coppia (name value)")))) -(defun type-check-field (field value) - (if (eq (length field) 2) - t - (type-check value (third field)))) - (defun type-check (value type) (if (is-class type) (if (is-instance value type) diff --git a/Lisp/ool.lisp b/Lisp/ool.lisp index 45377ca..f57e793 100644 --- a/Lisp/ool.lisp +++ b/Lisp/ool.lisp @@ -185,11 +185,9 @@ (cdr (cdr new-fields))))) (defun set-instance-field (instance name value) - ;; `setf` modifica in-place (setf (getf instance :fields) (set-field (getf instance :fields) name value)) - ;; quindi serve resistuire `instance` instance) (defun set-field (fields name value) @@ -211,10 +209,17 @@ (and (listp instance) (eq (getf instance :type) 'object))) - (and (listp instance) - (or (eq (getf instance :classname) class-name) - (member class-name (getf instance :parents))) - (eq (getf instance :type) 'object)))) + (or + (null instance) + (and (listp instance) + (or (eq (getf instance :classname) class-name) + (member class-name (getf instance :parents))) + (eq (getf instance :type) 'object))))) + +(defun type-check-field (field value) + (if (eq (length field) 2) + t + (type-check value (third field)))) (defun validate-fields-type (fields) (cond ((null fields) nil) @@ -236,11 +241,6 @@ "o è una terna (name value type)" "o una coppia (name value)")))) -(defun type-check-field (field value) - (if (eq (length field) 2) - t - (type-check value (third field)))) - (defun type-check (value type) (if (is-class type) (if (is-instance value type)