Prolog: Getting predicate solutions and asserting

2019-07-03 04:49发布

问题:

I've got a specific problem but I'll just try and come up with a general question so other people might benefit from it too...

I've got a predicate that returns many solutions i.e.

X=5; X=2; X=7

and I want a predicate that gets each of these solutions and asserts them as Prolog facts then so I end up with three facts in this case e.g.

fact(5) fact(2) fact(7)

so calling fact(5) would be true but calling fact(8) would be false because we never asserted it because it wasn't a solution.

But I don't want to have a predicate where you have to keep asking for solutions to assert each single fact. I want to call a predicate and have it go through all the solutions in the background, assert them and that's it.

One way of solving it is using findall to put all the solutions into a list and then just go through the list asserting each element of the list. However, I don't think this is very elegant. There must be a nicer way of doing it without fiddling around with lists.

回答1:

Use a failure-driven loop to force backtracking over all solutions:

?- computation(X), false.

You can ignore this query's declaratively false truth value with ignore/1:

?- ignore((computation(X),false)).


回答2:

This functionality can be made using setof and making a second order predicate.

:- dynamic fact/1.

isAns(5).
isAns(2).
isAns(7).

computation(F) :- setof(X,call(F,X),S),factify(S).

factify([X|Xs]) :- assert(fact(X)),factify(Xs).
factify([]).

Then when we go and ask about facts we get:

computation(isAns), fact(X).
X = 5;
X = 2;
X = 7;
false 


标签: prolog