-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
engine.Repeat how to #346
Comments
I really need to update that package, sorry about that. This discussion might be helpful: #163 (comment) |
Thanks but for me it is not clear to adapt this. It could be helpful to put some minimal examples to the wiki, I try to implement a "Predicate7" e.g I would like to do "data(A,B,C,E,F,G)" on Prolog side and it should iterate over an existing database table element by element |
Hi, you can achieve it with recursion. The basic idea is described in #163 (comment) (Thanks, @guregu!). Here's a detailed example that might work for you: package main
import (
"context"
"database/sql"
"log/slog"
"os"
"github.com/ichiban/prolog"
"github.com/ichiban/prolog/engine"
_ "modernc.org/sqlite"
)
type datum struct {
A, B, C, D, E, F, G string
}
func main() {
// Let's prepare an in-memory database with a table.
db, err := sql.Open("sqlite", ":memory:")
if err != nil {
slog.With("err", err).Error("failed to open database")
os.Exit(1)
}
if _, err := db.Exec(`CREATE TABLE data(a text, b text, c text, d text, e text, f text, g text);`); err != nil {
slog.With("err", err).Error("failed to create table")
os.Exit(1)
}
for _, d := range []datum{
{A: "a", B: "b", C: "c", D: "d", E: "e", F: "f", G: "g"},
{A: "h", B: "i", C: "j", D: "k", E: "l", F: "m", G: "n"},
{A: "o", B: "p", C: "q", D: "r", E: "s", F: "t", G: "u"},
} {
if _, err := db.Exec(`INSERT INTO data(a, b, c, d, e, f, g) VALUES (?, ?, ?, ?, ?, ?, ?);`, d.A, d.B, d.C, d.D, d.E, d.F, d.G); err != nil {
slog.With("err", err).Error("failed to insert data")
os.Exit(1)
}
}
p := prolog.New(nil, os.Stdout)
// Now let's define the custom predicate data/7.
p.Register7(engine.NewAtom("data"), func(vm *engine.VM, a, b, c, d, e, f, g engine.Term, cont engine.Cont, env *engine.Env) *engine.Promise {
// The first thing it does is to make a query and get rows.
rows, err := db.Query(`SELECT * FROM data;`)
if err != nil {
return engine.Error(err)
}
// Then, it does `k` recursively.
var k func(ctx context.Context) *engine.Promise
k = func(ctx context.Context) *engine.Promise {
// If the rows don't have any records left, it fails.
if !rows.Next() {
if err := rows.Close(); err != nil {
return engine.Error(err)
}
return engine.Bool(false)
}
// If a record exists, it scans the record.
var r datum
if err := rows.Scan(&r.A, &r.B, &r.C, &r.D, &r.E, &r.F, &r.G); err != nil {
return engine.Error(err)
}
// Then, it does either unify the record with the arguments or `k`.
return engine.Delay(func(ctx context.Context) *engine.Promise {
row := engine.NewAtom("row")
output := row.Apply(a, b, c, d, e, f, g)
input := row.Apply(engine.NewAtom(r.A), engine.NewAtom(r.B), engine.NewAtom(r.C), engine.NewAtom(r.D), engine.NewAtom(r.E), engine.NewAtom(r.F), engine.NewAtom(r.G))
return engine.Unify(vm, output, input, cont, env)
}, k)
}
return engine.Delay(k)
})
// Now you can call data/7.
_ = p.QuerySolution(`data(A, B, C, D, E, F, G), write(row(A, B, C, D, E, F, G)), write(.), nl, fail.`).Err()
}
|
Hello,
I try to add a database to my Prolog Go program, I'm following this idea with DynamoDB https://github.com/guregu/predicates/blob/master/dynamodb/dynamo.go#L66
But it seems that the engine.Repeat has been changed. How I can reach this with the current version? I have got a database with a lot of entries and I would like to iterate over each entry to and unify it for the return values.
Thanks a lot for help
The text was updated successfully, but these errors were encountered: