2
votes

I have predicate

superclass('Horde', 'Blood Elf').
superclass('Horde', 'Orc').

element('Blood Elf', ['Paladin', 'Priest','Mage','Warlock','Death Knight','Rogue']).
element('Orc', ['Warrior', 'Shaman','Warlock','Death Knight','Hunter','Rogue']).

find(A):-
  (  element(_,B),member(A,B)
  -> forall(
        ( element(_,B), member(A,B) ),
        ( element(C,B), superclass(D,C), format('~w -> ~w -> ~w\n',[D,C,A])))
  ;  superclass(A, _)
  -> format('~w\n',A), forall(superclass(A,B),format('\t~w\n',B))
  ).  

and two of results for find('Rogue').. After all, the predicate prints only 1 of them. However, when i copypaste forall(..) to console, it gives me all 2 results. Why?

1
How do you copypaste forall/2?false
forall((element(_,B),member('Rogue',B)),(element(C,B),superclass(D,C),format('~w -> ~w -> ~w\n',[D,C,'Rogue'])).defusioner

1 Answers

2
votes

Essentially, you have a single (->)/2 that is If -> Then. The If is in your case

( element(_,B), member(A,B) )

takes the very first answer and commits to it, thus other answers will not be considered. The Then is a forall/2 which either succeeds once or fails. So, there should never be a situation where you get more than one answer.


So you are comparing the original program to the query:

?- forall(
      (  element(_,B), member('Rogue',B) ),
      (  element(C,B),
         superclass(D,C),
         format('~w -> ~w -> ~w\n',[D,C,'Rogue'])
      )).

But the original program was different! It essentially was:

?- element(_,B),member(A,B)
    -> forall(
          (  element(_,B), member(A,B) ),
          (  element(C,B),
             superclass(D,C),
             format('~w -> ~w -> ~w\n',[D,C,A]))).

So in the original program A and B were fixed, whereas in your query, only A is fixed.

Note that programming in this manner by writing things out, often leads to all kinds of errors that are unrelated to Prolog itself. I'd rather recommend, that you first stick to the pure, monotonic subset of Prolog.