Skip to content

Commit 1706104

Browse files
committed
chore: update readme
1 parent 3f21c23 commit 1706104

File tree

2 files changed

+215
-30
lines changed

2 files changed

+215
-30
lines changed

README.md

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,180 @@
33
<p style="text-align: center">
44
<img src="docs/static/img/logos/Prolog_as_scalaDSL_BOW.png">
55
</p>
6+
7+
Prolog-as-scalaDSL is a library providing a DSL for writing Prolog programs in scala.
8+
9+
## How to use
10+
11+
1. Add the following library dependency in your build file.
12+
* for sbt:
13+
```scala
14+
libraryDependencies += "io.github.kelvindev15" % "prolog-as-scaladsl_3" % "<version>"
15+
```
16+
* for gradle:
17+
```kotlin
18+
implementation("io.github.kelvindev15:prolog-as-scaladsl_3:<version>")
19+
```
20+
2. Replace `<version>` with the desired of latest version of the library.
21+
22+
## Demo
23+
Using the DSL is as simple as extending the `PrologDSL` trait. Let's write a program.
24+
25+
```scala 3
26+
object Demo extends PrologDSL:
27+
def main(args: Array[String]): Unit =
28+
val program = PrologProgram(Theory(
29+
factOf(structOf(atomOf("father"), atomOf("abraham"), atomOf("isaac"))),
30+
factOf(structOf(atomOf("father"), atomOf("terach"), atomOf("abraham"))),
31+
ruleOf(
32+
structOf(atomOf("grandfather"), varOf("X"), varOf("Y")),
33+
structOf(atomOf("father"), varOf("X"), varOf("Z")) and
34+
structOf(atomOf("father"), varOf("Z"), varOf("Y")))),
35+
)
36+
37+
for
38+
solution <- Solver solve (
39+
program withGoal structOf(atomOf("father"), atomOf("abraham"), atomOf("isaac")))
40+
do println(solution)
41+
```
42+
43+
Here's the output:
44+
45+
```text
46+
Yes(father(abraham, isaac),Map())
47+
```
48+
49+
As you can tell the writing of the prolog program is a bit difficult since we had to specify what is a struct, what
50+
is an atom or a variable, etc... Fortunately we are in scala so we can take advantage of that:
51+
52+
```scala 3
53+
val father = atomOf("father")
54+
val grandfather = atomOf("grandfather")
55+
val abraham = atomOf("abraham")
56+
val isaac = atomOf("isaac")
57+
val terach = atomOf("terach")
58+
val X = varOf("X")
59+
val Y = varOf("Y")
60+
val Z = varOf("Z")
61+
62+
val program = PrologProgram(Theory(
63+
factOf(structOf(father, abraham, isaac)),
64+
factOf(structOf(father, terach, abraham)),
65+
ruleOf(structOf(grandfather, X, Y), structOf(father, X, Z) and structOf(father, Z, Y))),
66+
)
67+
```
68+
Now the program was easier to write, but, still we had to introduce a lot of variables in order to achieve that.
69+
Luckily the DSL come with some of predefined structures such as variables and moreover strings are automatically converted
70+
to atoms!
71+
72+
```scala 3
73+
val program = PrologProgram(theory(
74+
factOf(structOf("father", "abraham", "isaac")),
75+
factOf(structOf("father", "terach", "abraham")),
76+
ruleOf(structOf("grandfather", X, Y), structOf("father", X, Z) and structOf("father", Z, Y))),
77+
)
78+
```
79+
80+
In order to resemble the prolog syntax, string can be invoked to create structures:
81+
82+
```scala 3
83+
val program = PrologProgram(theory(
84+
factOf("father"("abraham", "isaac")),
85+
factOf("father"("terach", "abraham")),
86+
ruleOf("grandfather"(X, Y), "father"(X, Z) and "father"(Z, Y)),
87+
))
88+
```
89+
90+
The grandfather rule can be written in a "more prolog" way as:
91+
92+
```scala 3
93+
"grandfather"(X, Y) :- ("father"(X, Z) &: "father"(Z, Y))
94+
```
95+
96+
Whenever a clause is expected (e.g the arguments of the theory method), structure are automatically converted to fact.
97+
So here's a cleaner way to write the program.
98+
99+
```scala 3
100+
val program = PrologProgram(theory(
101+
"father"("abraham", "isaac"),
102+
"father"("terach", "abraham"),
103+
"grandfather"(X, Y) :- ("father"(X, Z) &: "father"(Z, Y)))
104+
)
105+
```
106+
107+
Let's make some other queries:
108+
109+
```scala 3
110+
for
111+
goal <- Seq(
112+
"grandfather"("abraham", "isaac"),
113+
"father"(A, "isaac"),
114+
"father"(F, S)
115+
)
116+
solution <- Solver solve (program withGoal goal)
117+
do println(solution)
118+
119+
/* OUTPUT:
120+
No(grandfather(abraham, isaac))
121+
Yes(father(A, isaac),Map(A -> abraham))
122+
Yes(father(F, S),Map(F -> abraham, S -> isaac))
123+
Yes(father(F, S),Map(F -> terach, S -> abraham))
124+
*/
125+
```
126+
127+
As you can see some solutions have a mapping (substitution). In this cases we can access a variable substitution directly
128+
from the solution:
129+
130+
```scala 3
131+
for
132+
solution <- Solver solve (program withGoal "father"(F, S))
133+
do
134+
for
135+
father <- solution(F)
136+
son <- solution(S)
137+
do println(s"$father is the father of $son")
138+
139+
/* OUTPUT
140+
abraham is the father of isaac
141+
terach is the father of abraham
142+
*/
143+
```
144+
145+
Program may be written in a more declarative way. All we need is to mixin the `DeclarativeProlog` trait.
146+
147+
```scala 3
148+
object Demo extends PrologDSL with DeclarativeProlog:
149+
def main(args: Array[String]): Unit =
150+
val program = prolog:
151+
programTheory:
152+
clause { "father"("abraham", "isaac") }
153+
clause { "father"("terach", "abraham") }
154+
clause { "grandfather"(X, Y) :- ("father"(X, Z) &: "father"(Z, Y)) }
155+
goal:
156+
"father"(F, S)
157+
158+
for solution <- Solver solve program do println(solution)
159+
```
160+
If you want, you may split your theory in a `staticTheory` and a `dynamicTheory`
161+
(`programTheory` is an alias of `dynamicTheory).
162+
163+
A Solver may be used just to satisfy goals in the following way:
164+
165+
```scala 3
166+
for solution <- Solver query member(X, list("a", "b", "c")) do println(solution)
167+
/*
168+
Yes(member(X, [a, b, c]),Map(X -> a))
169+
Yes(member(X, [a, b, c]),Map(X -> b))
170+
Yes(member(X, [a, b, c]),Map(X -> c))
171+
No(member(X, [a, b, c]))
172+
*/
173+
```
174+
Notice that `member` and `list` and many others are facility methods to create their correspondent predicates.
175+
176+
The trait `TermConvertible` gives you the possibility to interpret your object as if they were terms. You just need
177+
to specify how to convert them to term. Here's a cumbersome but explicative example:
178+
179+
```scala 3
180+
def father(f: String, s: String): TermConvertible = new TermConvertible:
181+
override def toTerm: Struct = "father"(f, s)
182+
```

docs/docs/documentazione/analysis.md

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ sidebar_label: "Analisi"
66
# Dominio
77
Prolog è un linguaggio di programmazione basato sul paradigma di programmazione logica.
88
Un **programma logico** è un insieme di *assiomi* o *regole* che definiscono *relazioni* tra oggetti.
9-
In Prolog un oggetto è tutto ciò che si può rappresentare tramite un [*termine*](.).
9+
In Prolog un oggetto è tutto ciò che si può rappresentare tramite un [*termine*](#termini).
1010
Un programma Prolog consiste di un insieme di clausole, ciascuna delle quali codifica una data informazione come
1111
un fatto o una regola.
1212
La computazione di un programma logico in Prolog ha come obiettivo la deduzione di conseguenze logiche del programma.
@@ -18,7 +18,7 @@ Tre sono i concetti alla base della programmazione logica: *fatti*, *regole* e *
1818

1919
### Fatto
2020
Esprime l'esistenza di una relazione tra oggetti/termini. Si compone del nome della relazione,
21-
detto anche *predicato*, e di un numero arbitrario di *argomenti*. In Prolog una collezione di fatti (e [regole](.)),
21+
detto anche *predicato*, e di un numero arbitrario di *argomenti*. In Prolog una collezione di fatti (e [regole](#regola)),
2222
prende il nome di *database*.
2323

2424
### Interrogazione
@@ -29,7 +29,7 @@ Un interrogazione consiste di una lista di goal che devono essere soddisfatti co
2929
[unificazione](https://en.wikipedia.org/wiki/Unification_(computer_science)). Con goal si intende una relazione tra
3030
oggetti/termini (equivalentemente a quanto si è detto per un fatto). Qualora non sia possibile soddisfare completamente
3131
la lista di goal, l'esito dell'interrogazione sarà negativo, altrimenti sarà positivo ed eventualmente comprenderà anche
32-
una lista si sostituzioni di [variabili](.).
32+
una lista si sostituzioni di [variabili](#variabili).
3333

3434
### Regola
3535
Detta anche inferenza, mette in relazione un fatto con un insieme di altri fatti. Si compone di una testa
@@ -162,10 +162,8 @@ Alcuni predicati potrebbero richiedere particolari tipi di argomenti (es. per il
162162
che gli argomenti siano dei numeri). Cosa succede nel caso in cui questi requisiti non vengano rispettati dipende dalla
163163
specifica implementazione del motore che eseguira il programma.
164164

165-
* **':-'(X, Y)** infix
166-
* **','(X, Y)** infix
167-
168-
#### Predicati dinamici
165+
* **':-'(X, Y)** (operatore infisso).
166+
* **','(X, Y)** (operatore infisso).
169167

170168
#### Predicati
171169

@@ -188,7 +186,7 @@ specifica implementazione del motore che eseguira il programma.
188186
* **retract(X)**
189187
* **functor(T, F, N)**
190188
* **arg(N, T, A)**
191-
* **'=..'(X, L)** infix
189+
* **'=..'(X, L)** (operatore infisso)
192190
* **atom_chars(A, L)**
193191
* **number_chars(A, L)**
194192

@@ -199,35 +197,45 @@ specifica implementazione del motore che eseguira il programma.
199197

200198
##### Costruzione di termini composti
201199

202-
* **';'(X, Y)** infix
200+
* **';'(X, Y)** (operatore infisso)
203201
* **call(X)**
204-
* **'\\+'(X)** prefix
202+
* **'\\+'(X)** (operatore infisso)
205203

206204
##### Uguaglianza
207205

208-
* **'='(X, Y)** infix
209-
* **'=='(X, Y)** infix
210-
* **op(X, Y, Z)** --> atoms fx, fy, xf, yf, xfx, yfx, yfy
211-
* **is(X, Y)** infix
206+
* **'='(X, Y)** (operatore infisso)
207+
* **'=='(X, Y)** (operatore infisso)
208+
* **op(X, Y, Z)**
209+
* **is(X, Y)** (operatore infisso)
212210

213211
##### Aritmetici
214212

215-
* **'+'(X, Y)** infix
216-
* **'-'(X, Y)** infix
217-
* **'*'(X, Y)** infix
218-
* **'/'(X, Y)** infix
219-
* **'//'(X, Y)** infix
220-
* **mod(X, Y)** infix
213+
I seguenti sono tutti operatori infissi.
214+
215+
* **'+'(X, Y)**
216+
* **'-'(X, Y)**
217+
* **'*'(X, Y)**
218+
* **'/'(X, Y)**
219+
* **'//'(X, Y)**
220+
* **mod(X, Y)**
221221

222222
##### Confronto fra termini
223223

224-
* **'=:='(X, Y)** infix
225-
* **'=\\='(X, Y)** infix
226-
* **'<'(X, Y)** infix
227-
* **'>'(X, Y)** infix
228-
* **'>='(X, Y)** infix
229-
* **'=<'(X, Y)** infix
230-
* **'@<'(X, Y)** infix
231-
* **'@>'(X, Y)** infix
232-
* **'@>='(X, Y)** infix
233-
* **'@=<'(X, Y)** infix
224+
I seguenti sono tutti operatori infissi.
225+
226+
* **'=:='(X, Y)**
227+
* **'=\\='(X, Y)**
228+
* **'<'(X, Y)**
229+
* **'>'(X, Y)**
230+
* **'>='(X, Y)**
231+
* **'=<'(X, Y)**
232+
* **'@<'(X, Y)**
233+
* **'@>'(X, Y)**
234+
* **'@>='(X, Y)**
235+
* **'@=<'(X, Y)**
236+
237+
238+
###### Riferimenti
239+
240+
* [Programming in Prolog, using the ISO standard - W. F. Clocksin, C. S. Mellish](https://link.springer.com/book/10.1007/978-3-642-55481-0)
241+
* [The Art of Prolog - L. Sterling, E. Shapiro](https://mitpress.mit.edu/9780262691635/the-art-of-prolog/)

0 commit comments

Comments
 (0)