Successful Predicate not filling Variable that must be unified.

18 views
Skip to first unread message

Stephen Coda

unread,
Apr 21, 2015, 7:00:58 AM4/21/15
to swi-p...@googlegroups.com
Hi everyone, thanks in advance to anyone who can help me here.

I'm new to Prolog and couldn't find an equivalent question to the one I'm posting so, given this knowledgebase:

t(pb(4)).
t(pb(4),L):-
member(pb(11),L).

tt(P,L):-
findall(T,t(P),R),
findall(T,t(P,L),R).

pv(A):-
tt(pb(4),[pb(A)]).


When I give the queries:

 ?- pv1(11).
true.

 ?- pv1(12).
false.

These are as I'd expect but, when I give:

 ?- pv1(A).
true.

This too is right except it doesn't bind anything to A for me. Can anyone explain what's going on here and how i can sensibly get the binding?
With trace I can clearly see the correct unification taking place, highlighted purple:

   Call: (6) pv1(_G19347) ? creep
   Call: (7) tt(pb(4), [pb(_G19347)]) ? creep
^  Call: (8) findall(_G19430, t(pb(4)), _G19432) ? creep
   Call: (13) t(pb(4)) ? creep
   Exit: (13) t(pb(4)) ? creep
^  Exit: (8) findall(_G19426, user:t(pb(4)), [_G19440]) ? creep
^  Call: (8) findall(_G19426, t(pb(4), [pb(_G19347)]), [_G19440]) ? creep
   Call: (13) t(pb(4), [pb(_G19347)]) ? creep
   Call: (14) lists:member(pb(11), [pb(_G19347)]) ? creep
   Exit: (14) lists:member(pb(11), [pb(11)]) ? creep
   Exit: (13) t(pb(4), [pb(11)]) ? creep
^  Exit: (8) findall(_G19426, user:t(pb(4), [pb(_G19347)]), [_G19440]) ? creep
   Exit: (7) tt(pb(4), [pb(_G19347)]) ? creep
   Exit: (6) pv1(_G19347) ? creep

So I just don't understand why there's no binding for A. This is all a simple instance of the code as I can get, the real version is validating a bunch of rules somewhat similar to 't' in the example against a list of things.

Thanks once again for any advice.
Steve.

Kilian Evang

unread,
Apr 21, 2015, 8:10:39 AM4/21/15
to swi-p...@googlegroups.com
On 04/21/2015 01:00 PM, Stephen Coda wrote:
> This too is right except it doesn't bind anything to A for me. Can
> anyone explain what's going on here

findall(Template, Goal, Bag) finds all solutions for Goal and collects
the corresponding instantiations of Template in a list (Bag). The way it
finds multiple solutions is that after each solution, it *backtracks*
and tries to find another. Backtracking undoes variable bindings, so
after findall/3 exits, Template and Goal are in the same state as before
it was called, only Bag has been instantiated.

> and how i can sensibly get the binding?

How about not using findall/3 and calling t/[1,2] directly?

Stephen Coda

unread,
Apr 21, 2015, 9:16:04 AM4/21/15
to swi-p...@googlegroups.com
Thanks, 

I can call the t[1/2] directly. Originally I was trying to avoid this as I wouldn't necessarily since I didn't know how many t[1/2]s there would be.
Is there any way to enumerate a complete set of solutions to a given goal? Can't think of an obvious way myself.

Kilian Evang

unread,
Apr 21, 2015, 9:35:32 AM4/21/15
to swi-p...@googlegroups.com
On 04/21/2015 03:16 PM, Stephen Coda wrote:
> Is there any way to enumerate a complete set of solutions to a given
> goal? Can't think of an obvious way myself.

Interactively, you can enumerate all solutions to a query by hitting the
; key afer each solution, see
http://www.swi-prolog.org/man/quickstart.html#sec:2.1.2 .

To make a list of all solutions, use findall/3, e.g.:

?- findall(A, t(pb(4), [pb(A)]), As).
As = [11].

Stephen Coda

unread,
Apr 22, 2015, 4:59:49 AM4/22/15
to swi-p...@googlegroups.com
Thanks Kilian,

I've changed tack to enumerate my rule tests explicitly, since there's no strong reason not to, it just seemed a little inelegant.

Steve
Reply all
Reply to author
Forward
0 new messages