Skip to content
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

feature request time/1 and/or statistics/2 predicate #327

Open
Jean-Luc-Picard-2021 opened this issue Aug 10, 2024 · 3 comments
Open

feature request time/1 and/or statistics/2 predicate #327

Jean-Luc-Picard-2021 opened this issue Aug 10, 2024 · 3 comments

Comments

@Jean-Luc-Picard-2021
Copy link

Would it be possible to have some time/1 and
statistics/2 predicate? Its not listed here:

https://github.com/ichiban/prolog/wiki

Which is understandable, since the ISO core
standard doesn't mention it. But how

about implementing it nevertheless since
many Prolog systems provide it now?

@ichiban
Copy link
Owner

ichiban commented Aug 14, 2024

What are you going to achieve with time/1 and statistics/2?

Since time/1 prints the result, it doesn't make sense to implement in this library. It might be useful in 1pl, though. Anyways, it'll be trivial to implement your own version as a custom predicate.

As for statistics/2, we might not be able to provide meaningful implementation since the internal structure is wildly different from other implementations.

@Jean-Luc-Picard-2021
Copy link
Author

Jean-Luc-Picard-2021 commented Aug 14, 2024

In case I would need to write my own time/1 I would
need statistics/2 anyway. Or is there some cpu_time evaluable
function. Didn't check yet.

time/1 is usually bootstrapped from statistics/2, but bootstrapping
time/1 is non triviail. time/1 has to cease time measurement while
the query prompt is shown, and time/1 can also measure

different backtracking results, like here in SWI-Prolog:

?- time((sleep(0.1);sleep(0.1))).
% -2 inferences, 0.000 CPU in 0.111 seconds (0% CPU, Infinite Lips)
true ;
% 7 inferences, 0.000 CPU in 0.104 seconds (0% CPU, Infinite Lips)
true.

A novice programmer doesn't know how to implement it. A
more advanced programmer can implement it, but you need
some state record, does Ichinban Prolog have a change_arg/3

predicate? It goes by the name nb_setarg/3.

@ichiban
Copy link
Owner

ichiban commented Aug 17, 2024

You can define your own time/1 (and also sleep/1) like this:

package main

import (
	"fmt"
	"time"

	"github.com/ichiban/prolog"
	"github.com/ichiban/prolog/engine"
)

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

	p.Register1(engine.NewAtom("time"), func(vm *engine.VM, g engine.Term, k engine.Cont, env *engine.Env) *engine.Promise {
		t := time.Now()
		return engine.Call(vm, g, func(env *engine.Env) *engine.Promise {
			fmt.Printf("time: %s\n", time.Now().Sub(t))
			t = time.Now()
			return k(env)
		}, env)
	})

	p.Register1(engine.NewAtom("sleep"), func(_ *engine.VM, s engine.Term, k engine.Cont, env *engine.Env) *engine.Promise {
		var d time.Duration
		switch s := env.Resolve(s).(type) {
		case engine.Variable:
			return engine.Error(engine.InstantiationError(env))
		case engine.Integer:
			d = time.Duration(s) * time.Second
		case engine.Float:
			d = time.Duration(s * engine.Float(time.Second))
		default:
			return engine.Error(engine.TypeError(engine.NewAtom("number"), s, env))
		}
		time.Sleep(d)
		return k(env)
	})

	sols, err := p.Query(`time((sleep(0.1);sleep(0.1))).`)
	if err != nil {
		panic(err)
	}

	for sols.Next() {
	}

	if err := sols.Close(); err != nil {
		panic(err)
	}
}
time: 100ms
time: 100ms

Program exited.

https://go.dev/play/p/joiuZW3tzpw

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants