Closed flashpixx closed 3 months ago
Hi, @flashpixx!
Could you check the version, please? I tried to replicate the problem but the current version seems to work.
Perhaps, you're seeing a bug in previous versions.
package main
import (
"fmt"
"github.com/ichiban/prolog"
)
func main() {
p := prolog.New(nil, nil)
if err := p.Exec(`
host(ip("192.168.45.1"),name("foo.bar")).
host(ip("192.168.45.2"),name("xxx.yyy")).
allhosts(L) :- findall([X,Y], host(ip(X),name(Y)), L).
`); err != nil {
panic(err)
}
sol := p.QuerySolution(`allhosts(L).`)
if err := sol.Err(); err != nil {
panic(err)
}
var s struct {
L [][]string
}
if err := sol.Scan(&s); err != nil {
panic(err)
}
fmt.Println(s.L)
}
[[192.168.45.1 foo.bar] [192.168.45.2 xxx.yyy]]
Program exited.
Your example is working, but I'm using a map, because my queries are created by the user, so I didn't have fixed variable names and with the map it generated an issue: https://go.dev/play/p/Pc1komgBDwT
It create the error s.L undefined (type map[string]interface{} has no field or method L)
package main
import (
"fmt"
"github.com/ichiban/prolog"
)
func main() {
p := prolog.New(nil, nil)
if err := p.Exec(`
host(ip("192.168.45.1"),name("foo.bar")).
host(ip("192.168.45.2"),name("xxx.yyy")).
allhosts(L) :- findall([X,Y], host(ip(X),name(Y)), L).
`); err != nil {
panic(err)
}
sol := p.QuerySolution(`allhosts(L).`)
if err := sol.Err(); err != nil {
panic(err)
}
s := make(map[string]interface{})
if err := sol.Scan(&s); err != nil {
panic(err)
}
fmt.Println(s.L)
}
On normale (atomic) values it works with a map, but not in this case
It looks like you have a Go syntax error. To get L
from a map, you need to look it up with a string "L"
.
package main
import (
"fmt"
"github.com/ichiban/prolog"
)
func main() {
p := prolog.New(nil, nil)
if err := p.Exec(`
host(ip("192.168.45.1"),name("foo.bar")).
host(ip("192.168.45.2"),name("xxx.yyy")).
allhosts(L) :- findall([X,Y], host(ip(X),name(Y)), L).
`); err != nil {
panic(err)
}
sol := p.QuerySolution(`allhosts(L).`)
if err := sol.Err(); err != nil {
panic(err)
}
s := make(map[string]interface{})
if err := sol.Scan(&s); err != nil {
panic(err)
}
fmt.Println(s["L"])
}
[[[1 9 2 . 1 6 8 . 4 5 . 1] [f o o . b a r]] [[1 9 2 . 1 6 8 . 4 5 . 2] [x x x . y y y]]]
Program exited.
I'm using next
with
result := make([]map[string]interface{}, 0)
for r.Next() {
m := make(map[string]interface{})
result = append(result, m)
if err := r.Scan(&m); err != nil {
return nil, err
}
}
Based on the input query it could be return more than one result, but expecially in that case next
seems to return nil / false so the loop does not iterate
I found the error it seems that my instatiation of the interepeter creates different behaviour:
I do it with p := new(prolog.Interpreter)
and you do it with p := prolog.New(nil, nil)
, I have changes the main init call and it works
And a comment in relatio to #315 in exactly this case it is quite hard to deal with the character list, because here I get []interface{}
and in a map[string]interface{}
, so to create a Go string it is a lot of additional code necessary
Hello,
I try to get all facts with findall with this call:
If I call
allhosts(L).
it returns an empty result. I evaluate the script with swipl and it returnsIs it possible to run findall with a list argument?
Thanks a lot