Git Product home page Git Product logo

pengine's Introduction

pengine GoDoc

import "github.com/guregu/pengine"

Pengines: Prolog Engines client for Go. Pengines's motto is "Web Logic Programming Made Easy". This library lets you query SWI-Prolog from Go and from ichiban/prolog, a Prolog interpreter written in Go.

Development Status: beta. Feedback and contributions welcome!

Usage

This library supports both the JSON and Prolog format APIs. Additionally, an RPC predicate for ichiban/prolog is provided.

Configuration

client := pengine.Client{
    // URL of the pengines server, required.
    URL: "http://localhost:4242/pengine",

    // Application name, optional.
    Application: "pengines_sandbox",
    // Chunk is the number of query results to accumulate in one response. 1 by default.
    Chunk: 10,
    // SourceText is Prolog source code to load (optional, currently only supported for the JSON format).
    SourceText: "awesome(prolog).\n",
    // SourceURL specifies a URL of Prolog source for the pengine to load (optional).
    SourceURL: "https://example.com/script.pl",
}

JSON API

client.Ask returns an Answers[Solutions] iterator, but you can use the generic pengine.Ask[T] function to use your own types.

answers, err := client.Ask(ctx, "between(1,6,X)")
if err != nil {
	panic(err)
}
var got []json.Number
for as.Next() {
	cur := as.Current()
	x := cur["X"]
	got = append(got, x.Number)
}
// got = {"1", "2", "3", ...}
if err := answers.Error(); err != nil {
	panic(err)
}

You can also use client.Create to create a pengine and Ask it later. If you need to stop a query early or destroy a pengine whose automatic destruction was disabled, you can call client.Close.

Prolog API

client.AskProlog returns ichiban/prolog/engine.Term objects. This uses the ichiban/prolog parser to handle results in the Prolog format. Use this for the most accurate representation of Prolog terms, but be aware that the parser does not support all of SWI's bells and whistles.

You can also call pengine.Term.Prolog() to get Prolog terms from the JSON results, but they might be lossy in terms of Prolog typing.

Warning about Unicode atoms

SWI-Prolog's defaults around Unicode cause errors for our Prolog parser at the moment, so we need to tweak the configuration.

  • We can't handle SWI's \uXXXX Unicode escapes.
    • This can interfere with unification of query results and cause unexpected "no solutions found" errors.

Luckily, Pengines makes it easy for us to customize the result formatter and fix this. Just define a pengines:write_result/3 hook for the prolog format on your Pengines server.

Here's an example of a working Pengines configuration:

pengines:write_result(prolog, Event, _) :-
    format('Content-type: text/x-prolog; charset=UTF-8~n~n'),
    write_term(Event,
               [ quoted(true),
                 quote_non_ascii(true),            % πŸ‘ˆ
                 character_escapes_unicode(false), % πŸ‘ˆ
                 ignore_ops(true),
                 fullstop(true),
                 blobs(portray),
                 portray_goal(pengines:portray_blob),
                 nl(true)
               ]).

RPC for ichiban/prolog

You can call remote pengines from ichiban/prolog, a Go Prolog, as well.

pengine_rpc/3 mostly works like its SWI-Prolog counterpart. Not all the options are implemented yet, but it seems to work OK!

interpreter.Register3("pengine_rpc", pengine.RPC)
:- pengine_rpc('http://localhost:4242/pengine', between(1,50,X), [chunk(10)]), write(X), nl.
% 1 2 3 4 ...

Tests

Currently the tests are rather manual:

% from swipl
consult(example_server).
# from OS terminal
go test -v

Change the pengines server URL used by the tests with the --pengines-server command line flag.

Other languages

Check out these pengines clients for other languages.

Thanks

  • TorbjΓΆrn Lager, Jan Wielemaker, and everyone else who has contributed to SWI-Prolog and Pengines.
  • @ian-andrich for the Python implementation, which was a handy reference for making this.
  • @ichiban for the awesome Prolog interpreter in Go.
  • Markus Triska for the wonderful tutorial series The Power of Prolog, which started me on my logic programming journey.

License

BSD 2-clause.

pengine's People

Contributors

guregu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

isgasho

pengine's Issues

Server library

Currently we have a Pengines client but no Pengines server.
Might be cool if we could implement part of the server bits as well.
Not super high priority but would be a fun project.

try Prolog format results instead of JSON

maybe optionally

seems like there's some ambiguity in the JSON representation of Prolog terms
(how do you distinguish an atom like 'A' and a variable A? both seem to be "A" in JSON)
(does this matter? πŸ€”)

encoding issues with Prolog API

Atom quoting

SWI doesn't quote non-ASCII by default, but ichiban/prolog requires it. So Japanese, for example 'ζΌ’ε­—' will break it.

There's a workaround:

pengines:write_result(prolog, Event, _) :-
    format('Content-type: text/x-prolog; charset=UTF-8~n~n'),
    write_term(Event,
               [ quoted(true),
                 quote_non_ascii(true),           % πŸ†•
                 character_escapes_unicode(true), % πŸ†•
                 ignore_ops(true),
                 fullstop(true),
                 blobs(portray),
                 portray_goal(portray_blob),
                 nl(true)
               ]).

Operator quoting

Our Write params in predicate.go aren't good enough. We need to pass at LEAST the comma operator to engine.Write to avoid sending invalid code like , (foo, bar) which SWI doesn't like. Either fix it to be ','(foo, bar) or (foo, bar).

fix pengine_rpc/3 URL parameter

I think I implemented the URL param (first param) of pengine_rpc/3 wrong. Need to double check. Seems like the official one tacks on /pengine to the URL but we don't.
Would be a breaking change.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.