prolog

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 22, 2021 License: MIT Imports: 10 Imported by: 32

README

ichiban/prolog

A Go embeddable Prolog.

Getting Started

Prerequisites

You need Go 1.6 or above installed.

Installation
go get -u github.com/ichiban/prolog@latest

Usage

Embed Prolog into Go
package main

import (
	"fmt"

	"github.com/ichiban/prolog"
)

// http://www.cse.unsw.edu.au/~billw/dictionaries/prolog/cut.html
func main() {
	p := prolog.New(nil, nil)
	if err := p.Exec(`
teaches(dr_fred, history).
teaches(dr_fred, english).
teaches(dr_fred, drama).
teaches(dr_fiona, physics).

studies(alice, english).
studies(angus, english).
studies(amelia, drama).
studies(alex, physics).
`); err != nil {
		panic(err)
	}

	for _, q := range []string{
		`teaches(dr_fred, Course), studies(Student, Course).`,
		`teaches(dr_fred, Course), !, studies(Student, Course).`,
		`teaches(dr_fred, Course), studies(Student, Course), !.`,
		`!, teaches(dr_fred, Course), studies(Student, Course).`,
	} {
		fmt.Printf("%s\n", q)

		sols, err := p.Query(q)
		if err != nil {
			panic(err)
		}

		for sols.Next() {
			var s struct {
				Course  string
				Student string
			}
			if err := sols.Scan(&s); err != nil {
				panic(err)
			}
			fmt.Printf("\t%+v\n", s)
		}

		fmt.Printf("\n")
		if err := sols.Close(); err != nil {
			panic(err)
		}
	}
}
$ go run examples/embed_prolog_into_go/main.go 
teaches(dr_fred, Course), studies(Student, Course).
        {Course:english Student:alice}
        {Course:english Student:angus}
        {Course:drama Student:amelia}

teaches(dr_fred, Course), !, studies(Student, Course).

teaches(dr_fred, Course), studies(Student, Course), !.
        {Course:english Student:alice}

!, teaches(dr_fred, Course), studies(Student, Course).
        {Course:english Student:alice}
        {Course:english Student:angus}
        {Course:drama Student:amelia}

Call Go from Prolog
package main

import (
	"fmt"
	"net/http"

	"github.com/ichiban/prolog"
	"github.com/ichiban/prolog/nondet"
	"github.com/ichiban/prolog/term"
)

func main() {
	p := prolog.New(nil, nil)

	// Define a custom predicate of arity 2.
	p.Register2("get_status", func(url, status term.Interface, k func(term.Env) *nondet.Promise, env *term.Env) *nondet.Promise {
		// Check if the input arguments are of the types you expected.
		u, ok := env.Resolve(url).(term.Atom)
		if !ok {
			return nondet.Error(fmt.Errorf("%s is not an atom", url))
		}

		// Do whatever you want with the given inputs.
		resp, err := http.Get(string(u))
		if err != nil {
			return nondet.Error(err)
		}

		// Return values by unification with the output arguments.
		if !status.Unify(term.Integer(resp.StatusCode), false, env) {
			return nondet.Bool(false)
		}

		// Tell Prolog to continue with the given continuation and environment.
		return k(*env)
	})

	sols, err := p.Query(`get_status('https://httpbin.org/status/200', Status).`)
	if err != nil {
		panic(err)
	}
	defer func() {
		if err := sols.Close(); err != nil {
			panic(err)
		}
	}()

	if !sols.Next() {
		panic("no solutions")
	}

	var s struct {
		Status int
	}
	if err := sols.Scan(&s); err != nil {
		panic(err)
	}

	fmt.Printf("%+v\n", s)
}
$ go run examples/call_go_from_prolog/main.go 
{Status:200}

License

Distributed under the MIT license. See LICENSE for more information.

Contributing

See ARCHITECTURE.md for architecture details.

  1. Fork it (https://github.com/ichiban/prolog/fork)
  2. Create your feature branch (git checkout -b feature/fooBar)
  3. Commit your changes (git commit -am 'Add some fooBar')
  4. Push to the branch (git push origin feature/fooBar)
  5. Create a new Pull Request

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Interpreter added in v0.2.0

type Interpreter struct {
	engine.VM
}

Interpreter is a Prolog interpreter. The zero value is a valid interpreter without any predicates/operators defined.

func New added in v0.2.0

func New(in io.Reader, out io.Writer) *Interpreter

New creates a new Prolog interpreter with predefined predicates/operators.

func (*Interpreter) Exec added in v0.2.0

func (i *Interpreter) Exec(query string, args ...interface{}) error

Exec executes a prolog program.

func (*Interpreter) Query added in v0.2.0

func (i *Interpreter) Query(query string, args ...interface{}) (*Solutions, error)

Query executes a prolog query and returns *Solutions.

type Solutions added in v0.2.0

type Solutions struct {
	// contains filtered or unexported fields
}

Solutions is the result of a query. Everytime the Next method is called, it searches for the next solution. By calling the Scan method, you can retrieve the content of the solution.

func (*Solutions) Close added in v0.2.0

func (s *Solutions) Close() error

Close closes the Solutions and terminates the search for other solutions.

func (*Solutions) Err added in v0.2.0

func (s *Solutions) Err() error

Err returns the error if exists.

func (*Solutions) Next added in v0.2.0

func (s *Solutions) Next() bool

Next prepares the next solution for reading with the Scan method. It returns true if it finds another solution, or false if there's no further solutions or if there's an error.

func (*Solutions) Scan added in v0.2.0

func (s *Solutions) Scan(dest interface{}) error

Scan copies the variable values of the current solution into the specified struct/map.

func (*Solutions) Vars added in v0.2.0

func (s *Solutions) Vars() []string

Vars returns variable names.

Directories

Path Synopsis
cmd
1pl
examples

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL