3

I don't understand why my predicate doesnt backtrack and find all solutions.

person(john).
person(erik).

allExceptSpider(person(Spider),T ):-
    setof(person(X),person(X),S),
    subtract(S,[person(Spider) ],T).

If I call this predicate with Two variables:

allExceptSpider(person(Z),Q)

Then it will only give me the answer Z = john, Q = [person(erik)] but it won't backtrack to find Z = erik ,Q = [person(john)] why?

J.doe
  • 373
  • 2
  • 14
  • 1
    Because of subtract/3 signature: +,+,-. The second argument should be ground. – CapelliC Jun 05 '16 at 04:10
  • @CapelliC. Mode specs are sloppy. cf https://sicstus.sics.se/sicstus/docs/latest4/html/sicstus.html/Mode-Spec.html . IIRC "++" is used by some processors to indicate "should be ground". – repeat Jun 05 '16 at 05:11

1 Answers1

3

TL;DR: If you use subtract/3 , your code may lose .

person(john).
person(erik).

allExceptSpider(Spider, T) :-
   setof(X, person(X), S),
   subtract(S, [Spider], T).

Preserve purity! How? Use list_item_subtracted/3 like so:

allExceptSpiderNU(Spider, T) :-
   setof(X, person(X), S),
   list_item_subtracted(S, Spider, T).

Sample queries head-to-head:

?- allExceptSpider(Z, Q).
Q = [erik], Z = john.

?- allExceptSpiderNU(Z,Q).
   Q = [     erik]             ,     Z=john
;  Q = [john     ],     Z=erik
;  Q = [john,erik], dif(Z,erik), dif(Z,john).
Community
  • 1
  • 1
repeat
  • 18,496
  • 4
  • 54
  • 166