Closed lynerist closed 2 months ago
This is not missing. And findall/3
is not a good replacement. It's in some implementations offered as a double (\+)/1
with all its weak points. To take your example:
?- X = a, valid(X).
X = a.
?- valid(X), X = a.
false, unexpected.
If it's not missing then it's my bad, I'm sorry. But then, why if I run this code (where p is a *prolog.Interpreter) :
p.Exec(`
valid(X) :-
forall(needs(X,Y),
exists(Y)).
exists(a).
exists(b).
needs(x,a).
needs(x,b).
needs(y,b).
needs(y,c).
`)
with the query
p.Query("valid(x).")
The resulting *prolog.Solution is empty? I mean, the Next method returns false and there is no solution.
btw when I said that I'll use the findall/3
to replace it I meant to rewrite valid in this way:
valid(X) :-
findall(Y, needs(X, Y), Needed),
maplist(exists, Needed).
If it's not missing then it's my bad, I'm sorry.
My fault. What I meant was that this forall/2
is a rather problematic predicate. So it does not make sense to include it into the set of built-in predicates. And thus it is "not missing".
It was considered to be included into the standard. Last time was N208, but later it was not included into Cor.2 (all below the double line was rejected).
In general, when trying out Prolog, I would suggest to first use the top level loop, and not an interface via another programming language since such interfaces are often optimized for certain uses only.
Your definition of valid/1
has a similar problem with the most general query ?- valid(X).
as this will succeed only if all needed things exist. And if a single does not exist, it will fail.
Hi, @lynerist
As you found out, forall/2
isn't in this library. We only include standardized predicates.
Luckily, you can easily implement forall/2
like this:
package main
import (
"fmt"
"github.com/ichiban/prolog"
)
func main() {
p := prolog.New(nil, nil)
if err := p.Exec(`
forall(Condition, Action) :- \+ (Condition, \+Action).
valid(X) :- forall(needs(X,Y), exists(Y)).
exists(a).
exists(b).
needs(x,a).
needs(x,b).
needs(y,b).
needs(y,c).
`); err != nil {
panic(err)
}
for _, q := range []string{
`X = x, valid(X).`, `valid(X), X = x.`,
`X = y, valid(X).`, `valid(X), X = y.`,
`X = z, valid(X).`, `valid(X), X = z.`,
} {
s := p.QuerySolution(q)
fmt.Printf("%s ==> %t\n", q, s.Err() == nil)
}
}
X = x, valid(X). ==> true
valid(X), X = x. ==> false
X = y, valid(X). ==> false
valid(X), X = y. ==> false
X = z, valid(X). ==> true
valid(X), X = z. ==> false
Program exited.
https://go.dev/play/p/xMb1_IS0_Oh
Of course, you should be careful with the weird behaviour of forall/2
@UWN pointed out. (Thank you for the insight!)
But for me, it feels more natural to encode the requirements as bodies of valid/1
like this:
package main
import (
"fmt"
"github.com/ichiban/prolog"
)
func main() {
p := prolog.New(nil, nil)
if err := p.Exec(`
valid(x) :- exists(a), exists(b).
valid(y) :- exists(b), exists(c).
valid(z).
exists(a).
exists(b).
`); err != nil {
panic(err)
}
for _, q := range []string{
`X = x, valid(X).`, `valid(X), X = x.`,
`X = y, valid(X).`, `valid(X), X = y.`,
`X = z, valid(X).`, `valid(X), X = z.`,
} {
s := p.QuerySolution(q)
fmt.Printf("%s ==> %t\n", q, s.Err() == nil)
}
}
X = x, valid(X). ==> true
valid(X), X = x. ==> true
X = y, valid(X). ==> false
valid(X), X = y. ==> false
X = z, valid(X). ==> true
valid(X), X = z. ==> true
Program exited.
Ok thank you very much! I'm pretty new in Prolog and I'm using swipl compiler to test programs before to implement them in Go, due to the fact that they implemented "forall" I thought it was in the standard.
I'll implement it as @ichiban suggested, thank you for the advice.
Anyway I can't include the requirements as bodies
But for me, it feels more natural to encode the requirements as bodies of valid/1 like this:
because they change with the input and in the time so I need valid/1 to be a function.
I need to implement something like that:
% ?- valid(x). % =>true % ?- valid(y). % => false % ?- valid(z). % => true
But it seems that the forall predicate is missing in the repository. I'll use the findall to replace it but it would be a great improvement to add the forall.