From: LeonardoBizzoni Date: Sat, 30 Dec 2023 10:47:30 +0000 (+0100) Subject: Aggiunti commenti al codice prolog X-Git-Url: http://git.leonardobizzoni.com/?a=commitdiff_plain;h=41df1600b1084b707ac38c0645e577092b3aa85c;p=ObjectOriented-Prolog-Lisp Aggiunti commenti al codice prolog --- diff --git a/Prolog/README.org b/Prolog/README.org index fded359..8c0b1f8 100644 --- a/Prolog/README.org +++ b/Prolog/README.org @@ -35,6 +35,9 @@ def_class(ClassName, Parents, Parts) :- is_list(Parents), is_list(Parts), \+ wrapped_def_class(ClassName, Parents, Parts), + + %% Se fallisce la definizione della classe + %% elimina le informazioni residue dalla base di conoscenza retractall(is_class(ClassName)), retractall(is_class(ClassName, _)), retractall(is_child_of(_, ClassName)), @@ -131,36 +134,34 @@ Descrivi un costruttore di Java. *** Implementazione #+begin_src prolog :tangle oop.pl make(InstanceName, ClassName) :- - var(InstanceName), - nonvar(ClassName), - is_class(ClassName), - !, - search_instance(InstanceName, ClassName, []). + make(InstanceName, ClassName, []). -make(InstanceName, ClassName) :- - atom(InstanceName), +make(InstanceName, ClassName, Fields) :- + var(InstanceName), nonvar(ClassName), is_class(ClassName), !, - make(InstanceName, ClassName, []). + search_instance(InstanceName, ClassName, Fields). make(InstanceName, ClassName, Fields) :- + atom(InstanceName), nonvar(InstanceName), + is_class(ClassName), wrapped_make(InstanceName, ClassName, Fields), !. make(InstanceName, ClassName, Fields) :- + atom(InstanceName), nonvar(InstanceName), + is_class(ClassName), \+ wrapped_make(InstanceName, ClassName, Fields), - !, + + %% Se fallisce la definizione dell'instance + %% elimina le informazioni residue dalla base di conoscenza retractall(is_instance(InstanceName)), retractall(is_instance(InstanceName, _)), retractall(field(InstanceName, _, _)), fail(). - -make(InstanceName, ClassName, Fields) :- - var(InstanceName), - search_instance(InstanceName, ClassName, Fields). #+end_src *** Esempio pratico @@ -174,6 +175,7 @@ make(root, node, [value = 200]). %% true. make(Instance, foobar). %% Instance = fb. make(Instance, bar, [bar = "69"]). %% Instance = b; false. #+end_src + ** field *** Definizione Estrae il valore di una classe da un campo @@ -220,6 +222,24 @@ fieldx(Instance, [FieldName | Others], Res) :- fieldx(fb, [foo,bar,foobar], Result). #+end_src +** inst +*** Definizione +Dato un oggetto che rappresenta un'istanza restituisce il nome dell'istanza. +Si nella nostra implementazione è banale perchè l'oggetto che rappresenta l'istanza è il nome dell'istanza. + +*** Implementazione +#+begin_src prolog :tangle oop.pl +inst(InstanceName, InstanceName). +#+end_src + +*** Esempio pratico +#+begin_src prolog +inst(f, f). %% true. +inst(b, b). %% true. +inst(X, fb). %% X = fb. +inst(fb, root). %% false. +#+end_src + * Predicati helper ** Predicati dinamici Predicati usati con `assert` guarda dove vengono usati e scrivi 2 righe. @@ -247,7 +267,12 @@ add_part(ClassName, [field(Name, Value) | OtherParts]) :- is_class(ClassName), is_member(field(Name, _, _), ClassName), !, + + %% Se il field da aggiungere è anche un field di una superclass + %% allora rimuovilo della base di conoscenza retractall(is_member(field(Name, _, _), ClassName)), + + %% e sostituiscilo con il field della classe stessa asserta(is_member((field(Name, Value, nil)), ClassName)), add_part(ClassName, OtherParts). @@ -255,6 +280,9 @@ add_part(ClassName, [field(Name, Value) | OtherParts]) :- is_class(ClassName), \+ is_member(field(Name, _, _), ClassName), !, + + %% Se il field non è anche un field di una superclass + %% allora di che è un field di questa classe asserta(is_member((field(Name, Value, nil)), ClassName)), add_part(ClassName, OtherParts). #+end_src @@ -266,8 +294,15 @@ add_part(ClassName, [field(Name, Value, Type) | OtherParts]) :- is_class(ClassName), is_member(field(Name, _, _), ClassName), !, + + %% Se il field da aggiungere è anche un field di una superclass + %% allora rimuovilo della base di conoscenza retractall(is_member(field(Name, _, _), ClassName)), + + %% Controlla che il valore del field sia del tipo del field type_check(Type, Value), + + %% e sostituiscilo con il field della classe stessa asserta(is_member(field(Name, Value, Type), ClassName)), add_part(ClassName, OtherParts). @@ -275,8 +310,11 @@ add_part(ClassName, [field(Name, Value, Type) | OtherParts]) :- is_class(ClassName), \+ is_member(field(Name, _, _), ClassName), !, - retractall(is_member(field(Name, _, _), ClassName)), + + %% Se il field non è anche un field di una superclass + %% controlla che il valore del field sia del tipo del field type_check(Type, Value), + %% e di che è un field di questa classe asserta(is_member(field(Name, Value, Type), ClassName)), add_part(ClassName, OtherParts). #+end_src @@ -289,8 +327,11 @@ add_part(ClassName, [method(Name, ArgList, Body) | OtherParts]) :- is_list(ArgList), is_class(ClassName), asserta(is_member(method(Name, ArgList, Body), ClassName)), + + %% Ricava il termine composto che rappresenta la testa del predicato Head =.. [Name, InstanceName | ArgList], !, + replace(this, InstanceName, Body, NewBody), asserta(Head :- (is_instance(InstanceName, ClassName), NewBody, !)), add_part(ClassName, OtherParts). @@ -304,7 +345,9 @@ set_superclass_fields(_InstanceName, _ClassName, []) :- !. set_superclass_fields(InstanceName, ClassName, [[Name, Value, Type] | OtherFields]) :- + %% Controlla che il valore sia del tipo corretto type_check(Type, Value), + assertz(field(InstanceName, Name, Value)), set_superclass_fields(InstanceName, ClassName, OtherFields). #+end_src @@ -317,38 +360,48 @@ set_fields(_InstanceName, _ClassName, []) :- !. set_fields(InstanceName, ClassName, [=(Name, Value) | OtherFields]) :- + %% Controlla che `Name` sia un field dell'istanza field(InstanceName, Name, OldValue), + %% ed un membro della classe is_member(field(Name, _Value, Type), ClassName), + + %% Controlla che il nuovo valore sia del tipo corretto type_check(Type, Value), - retractall(field(InstanceName, Name, OldValue)), !, + + %% Rimuove della base di conoscenza il vecchio field + retractall(field(InstanceName, Name, OldValue)), + %% e lo aggiorna con il nuovo valore asserta(field(InstanceName, Name, Value)), + set_fields(InstanceName, ClassName, OtherFields). +%% Se arriva a questo caso si è verificato un errore +%% e deve eliminare le informazioni residue +%% della creazione dell'istanza set_fields(InstanceName, _ClassName, _Fields) :- retractall(is_instance(InstanceName)), retractall(is_instance(InstanceName, _)), retractall(field(InstanceName, _, _)), - !, fail(). #+end_src -** Sostituzione di termine +** Sostituzione del termine `this` Magia nera chiedi a Mirko. #+begin_src prolog :tangle oop.pl -replace(Subterm0, Subterm, Term0, Term) :- - Term0 == Subterm0, - !, - Term = Subterm. -replace(_Subterm0, _Subterm, Term0, Term) :- - var(Term0), - !, - Term = Term0. -replace(Subterm0, Subterm, Term0, Term) :- - Term0 =.. [F | Args0], - maplist(replace(Subterm0,Subterm), Args0, Args), - Term =.. [F | Args]. +replace(OldTerm, NewTerm, Body, NewTerm) :- Body == OldTerm, !. +replace(_OldTerm, _NewTerm, Body, Body) :- var(Body), !. +replace(OldTerm, NewTerm, Body, Result) :- + Body =.. [Funct | BodyFunctArgs], + + %% Chiama ricorsivamente `replace` sugli argomenti di `Body` + maplist(replace(OldTerm,NewTerm), BodyFunctArgs, NewFunctArgs), + + %% Ricostruisci il termine composto con: + %% - stesso funtore di `Body` + %% - argomenti a cui è stata applicata la `replace` + Result =.. [Funct | NewFunctArgs]. #+end_src ** Controllo dei tipi @@ -409,6 +462,8 @@ set_superclass(ClassName, [Parent | OtherParents]) :- asserta(is_child_of(Parent, ClassName)), def_class(ClassName, OtherParents), + %% Trova tutti i field/method del genitore + %% e aggiungili alla classe figlio findall(Part, is_member(Part, Parent), ParentParts), @@ -420,25 +475,28 @@ set_superclass(ClassName, [Parent | OtherParents]) :- #+begin_src prolog :tangle oop.pl wrapped_make(InstanceName, ClassName, Fields) :- is_list(Fields), - !, - instanciate_superclass(InstanceName, ClassName), - set_fields(InstanceName, ClassName, Fields). -#+end_src - -*** Assegnamento dei valori ereditati dalla superclass all'istanza -#+begin_src prolog :tangle oop.pl -instanciate_superclass(InstanceName, ClassName) :- atom(InstanceName), nonvar(ClassName), is_class(ClassName), \+ is_instance(InstanceName), - !, + asserta(is_instance(InstanceName)), asserta(is_instance(InstanceName, ClassName)), + instanciate_superclass(InstanceName, ClassName), + set_fields(InstanceName, ClassName, Fields). +#+end_src + +*** Assegnamento dei valori ereditati dalla superclass all'istanza +#+begin_src prolog :tangle oop.pl +instanciate_superclass(InstanceName, ClassName) :- + %% Trova tutti i field della classe da istanziare + %% e raggruppali in terne (nome, valore, tipo) findall([Name, Value, Type], is_member(field(Name, Value, Type), ClassName), Fields), + + %% Dì per ogni field che è `field` dell'instance `InstanceName` set_superclass_fields(InstanceName, ClassName, Fields). #+end_src diff --git a/Prolog/oop.pl b/Prolog/oop.pl index 1d00590..b63a1f4 100644 --- a/Prolog/oop.pl +++ b/Prolog/oop.pl @@ -14,6 +14,9 @@ def_class(ClassName, Parents, Parts) :- is_list(Parents), is_list(Parts), \+ wrapped_def_class(ClassName, Parents, Parts), + + %% Se fallisce la definizione della classe + %% elimina le informazioni residue dalla base di conoscenza retractall(is_class(ClassName)), retractall(is_class(ClassName, _)), retractall(is_child_of(_, ClassName)), @@ -21,37 +24,35 @@ def_class(ClassName, Parents, Parts) :- fail(). make(InstanceName, ClassName) :- - var(InstanceName), - nonvar(ClassName), - is_class(ClassName), - !, - search_instance(InstanceName, ClassName, []). + make(InstanceName, ClassName, []). -make(InstanceName, ClassName) :- - atom(InstanceName), +make(InstanceName, ClassName, Fields) :- + var(InstanceName), nonvar(ClassName), is_class(ClassName), !, - make(InstanceName, ClassName, []). + search_instance(InstanceName, ClassName, Fields). make(InstanceName, ClassName, Fields) :- + atom(InstanceName), nonvar(InstanceName), + is_class(ClassName), wrapped_make(InstanceName, ClassName, Fields), !. make(InstanceName, ClassName, Fields) :- + atom(InstanceName), nonvar(InstanceName), + is_class(ClassName), \+ wrapped_make(InstanceName, ClassName, Fields), - !, + + %% Se fallisce la definizione dell'instance + %% elimina le informazioni residue dalla base di conoscenza retractall(is_instance(InstanceName)), retractall(is_instance(InstanceName, _)), retractall(field(InstanceName, _, _)), fail(). -make(InstanceName, ClassName, Fields) :- - var(InstanceName), - search_instance(InstanceName, ClassName, Fields). - :- dynamic field/3. fieldx(Instance, [FieldName], Res) :- @@ -62,6 +63,8 @@ fieldx(Instance, [FieldName | Others], Res) :- field(Instance, FieldName, _Value), fieldx(Instance, Others, Res). +inst(InstanceName, InstanceName). + :- dynamic is_class/1. :- dynamic is_child_of/2. :- dynamic is_member/2. @@ -69,11 +72,17 @@ fieldx(Instance, [FieldName | Others], Res) :- :- dynamic is_instance/2. add_part(ClassName, []) :- is_class(ClassName), !. + add_part(ClassName, [field(Name, Value) | OtherParts]) :- is_class(ClassName), is_member(field(Name, _, _), ClassName), !, + + %% Se il field da aggiungere è anche un field di una superclass + %% allora rimuovilo della base di conoscenza retractall(is_member(field(Name, _, _), ClassName)), + + %% e sostituiscilo con il field della classe stessa asserta(is_member((field(Name, Value, nil)), ClassName)), add_part(ClassName, OtherParts). @@ -81,6 +90,9 @@ add_part(ClassName, [field(Name, Value) | OtherParts]) :- is_class(ClassName), \+ is_member(field(Name, _, _), ClassName), !, + + %% Se il field non è anche un field di una superclass + %% allora di che è un field di questa classe asserta(is_member((field(Name, Value, nil)), ClassName)), add_part(ClassName, OtherParts). @@ -88,8 +100,15 @@ add_part(ClassName, [field(Name, Value, Type) | OtherParts]) :- is_class(ClassName), is_member(field(Name, _, _), ClassName), !, + + %% Se il field da aggiungere è anche un field di una superclass + %% allora rimuovilo della base di conoscenza retractall(is_member(field(Name, _, _), ClassName)), + + %% Controlla che il valore del field sia del tipo del field type_check(Type, Value), + + %% e sostituiscilo con il field della classe stessa asserta(is_member(field(Name, Value, Type), ClassName)), add_part(ClassName, OtherParts). @@ -97,8 +116,11 @@ add_part(ClassName, [field(Name, Value, Type) | OtherParts]) :- is_class(ClassName), \+ is_member(field(Name, _, _), ClassName), !, - retractall(is_member(field(Name, _, _), ClassName)), + + %% Se il field non è anche un field di una superclass + %% controlla che il valore del field sia del tipo del field type_check(Type, Value), + %% e di che è un field di questa classe asserta(is_member(field(Name, Value, Type), ClassName)), add_part(ClassName, OtherParts). @@ -106,9 +128,12 @@ add_part(ClassName, [method(Name, ArgList, Body) | OtherParts]) :- is_list(ArgList), is_class(ClassName), asserta(is_member(method(Name, ArgList, Body), ClassName)), + + %% Ricava il termine composto che rappresenta la testa del predicato Head =.. [Name, InstanceName | ArgList], !, - replace(this,InstanceName,Body,NewBody), + + replace(this, InstanceName, Body, NewBody), asserta(Head :- (is_instance(InstanceName, ClassName), NewBody, !)), add_part(ClassName, OtherParts). @@ -116,7 +141,9 @@ set_superclass_fields(_InstanceName, _ClassName, []) :- !. set_superclass_fields(InstanceName, ClassName, [[Name, Value, Type] | OtherFields]) :- + %% Controlla che il valore sia del tipo corretto type_check(Type, Value), + assertz(field(InstanceName, Name, Value)), set_superclass_fields(InstanceName, ClassName, OtherFields). @@ -124,33 +151,43 @@ set_fields(_InstanceName, _ClassName, []) :- !. set_fields(InstanceName, ClassName, [=(Name, Value) | OtherFields]) :- + %% Controlla che `Name` sia un field dell'istanza field(InstanceName, Name, OldValue), + %% ed un membro della classe is_member(field(Name, _Value, Type), ClassName), + + %% Controlla che il nuovo valore sia del tipo corretto type_check(Type, Value), - retractall(field(InstanceName, Name, OldValue)), !, + + %% Rimuove della base di conoscenza il vecchio field + retractall(field(InstanceName, Name, OldValue)), + %% e lo aggiorna con il nuovo valore asserta(field(InstanceName, Name, Value)), + set_fields(InstanceName, ClassName, OtherFields). +%% Se arriva a questo caso si è verificato un errore +%% e deve eliminare le informazioni residue +%% della creazione dell'istanza set_fields(InstanceName, _ClassName, _Fields) :- retractall(is_instance(InstanceName)), retractall(is_instance(InstanceName, _)), retractall(field(InstanceName, _, _)), - !, fail(). -replace(Subterm0, Subterm, Term0, Term) :- - Term0 == Subterm0, - !, - Term = Subterm. -replace(_Subterm0, _Subterm, Term0, Term) :- - var(Term0), - !, - Term = Term0. -replace(Subterm0, Subterm, Term0, Term) :- - Term0 =.. [F | Args0], - maplist(replace(Subterm0,Subterm), Args0, Args), - Term =.. [F | Args]. +replace(OldTerm, NewTerm, Body, NewTerm) :- Body == OldTerm, !. +replace(_OldTerm, _NewTerm, Body, Body) :- var(Body), !. +replace(OldTerm, NewTerm, Body, Result) :- + Body =.. [Funct | BodyFunctArgs], + + %% Chiama ricorsivamente `replace` sugli argomenti di `Body` + maplist(replace(OldTerm,NewTerm), BodyFunctArgs, NewFunctArgs), + + %% Ricostruisci il termine composto con: + %% - stesso funtore di `Body` + %% - argomenti a cui è stata applicata la `replace` + Result =.. [Funct | NewFunctArgs]. type_check(_X, nil) :- !. type_check(nil, _X) :- !. @@ -201,6 +238,8 @@ set_superclass(ClassName, [Parent | OtherParents]) :- asserta(is_child_of(Parent, ClassName)), def_class(ClassName, OtherParents), + %% Trova tutti i field/method del genitore + %% e aggiungili alla classe figlio findall(Part, is_member(Part, Parent), ParentParts), @@ -208,22 +247,25 @@ set_superclass(ClassName, [Parent | OtherParents]) :- wrapped_make(InstanceName, ClassName, Fields) :- is_list(Fields), - !, - instanciate_superclass(InstanceName, ClassName), - set_fields(InstanceName, ClassName, Fields). - -instanciate_superclass(InstanceName, ClassName) :- atom(InstanceName), nonvar(ClassName), is_class(ClassName), \+ is_instance(InstanceName), - !, + asserta(is_instance(InstanceName)), asserta(is_instance(InstanceName, ClassName)), + instanciate_superclass(InstanceName, ClassName), + set_fields(InstanceName, ClassName, Fields). + +instanciate_superclass(InstanceName, ClassName) :- + %% Trova tutti i field della classe da istanziare + %% e raggruppali in terne (nome, valore, tipo) findall([Name, Value, Type], is_member(field(Name, Value, Type), ClassName), Fields), + + %% Dì per ogni field che è `field` dell'instance `InstanceName` set_superclass_fields(InstanceName, ClassName, Fields). search_instance(InstanceName, ClassName, [=(Field,Value) | Other]) :-