Stephan Pillhofer
Stephan Pillhofer

Reputation: 147

Prolog - Predicate doesn't find all solutions when using no input variables

Here is my problem.

My facts and rules:

fact1(green, red, blue).
fact1(purple, white, gray).

fact2(green, orange).
fact2(purple, cyan).

fact3(green, pink).
fact3(purple, black).

foo(A,B,C,D,E) :-
   fact1(A,B,C),
   fact2(A,D),
   fact3(A,E),
   write(A),
   write(B).

Now if I ask SWI-Prolog foo(A,B,C,D,E). the output is

?- foo(A,B,C,D,E).
greenred
A = green, B = red, C = blue, D = orange, E = pink ;
purplewhite
A = purple, B = white, C = gray, D = cyan, E = black.

My goal is that the user only sees the lines

greenred
purplewhite

In order to achieve this I tried changing the definition of foo like so:

foo() :-
   fact1(A,B,C),
   fact2(A,D),
   fact3(A,E),
   write(A),
   write(B).

But the output of this predicate is only:

?- foo().
greenred
true.

and not what I would expect:

?- foo().
greenred
purplewhite
true.

Any help is very welcome.

Upvotes: 1

Views: 887

Answers (1)

Guy Coder
Guy Coder

Reputation: 24976

Adding fail/0 at the end tuns this into a failure driven loop so that once an answer is given, the predicate fails and tries the other choice points.

foo :-
    fact1(A,B,_),
    fact2(A,_),
    fact3(A,_),
    write(A),
    write(B),
    nl,
    fail.

Example run.

?- foo.
greenred
purplewhite
false.

To get Prolog to return true, (In the the background an evil voice says, "We have ways of making you give us the truth"), it needs to succeed after failing so Prolog looks for another clause named foo. By adding just foo. as a second clause Prolog can now find this clause and execute it. Since it does nothing, it succeeds and returns true.

foo.

Example run

?- foo.
greenred
purplewhite
true.

Complete source code

foo :-
    fact1(A,B,_),
    fact2(A,_),
    fact3(A,_),
    write(A),
    write(B),
    nl,
    fail.
foo.

Upvotes: 1

Related Questions