]> git.leonardobizzoni.com Git - ObjectOriented-Prolog-Lisp/commitdiff
Finita documentazione lisp
authorLeonardoBizzoni <leo2002714@gmail.com>
Thu, 11 Jan 2024 13:06:03 +0000 (14:06 +0100)
committerLeonardoBizzoni <leo2002714@gmail.com>
Thu, 11 Jan 2024 13:06:03 +0000 (14:06 +0100)
Lisp/README.org
Lisp/ool.lisp

index fdb0e4f516195674ee68d03e9cc620c880032d69..6c6779f3458fb726c31f9031b9afcb599290448b 100644 (file)
@@ -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)
index 45377ca67257902326d0a2bbbfdbb8e58506134f..f57e793d49b215f1669c10241826b31d9c3628bc 100644 (file)
        (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)
           (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)
              "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)