0

I'm new to prolog, and as I understand it, the purpose of 'distinct' is to weed out duplicates. However, this code block:

allpartsincity(City):-
    distinct((proj(Project, _, City), sppj(_, Part, Project, _), part(Part, _, _, _, _))),
    part(Part, Name, Color, Num, X),
    format('~w ~w ~w ~w ~w ~n', [Part, Name, Color, Num, X]),
    fail
    ;
    true.

yields the following:

?- allpartsincity(london).
p2 bolt green 17 paris 
p5 cam blue 12 paris 
p2 bolt green 17 paris 
p6 cog red 19 london 
p5 cam blue 12 paris 
true.

I'm not sure what I'm missing, but I'd appreciate if someone could point me in the right direction.

false
  • 10,264
  • 13
  • 101
  • 209
vio
  • 1
  • Avoid manual writing as with format. Instead, define a relation with more arguments such that the [tag:prolog-toplevel] can print it for you. In your case, `city_part(City, part(Part, Name, Color, Num, X)) :- ...` – false Feb 28 '20 at 10:57

2 Answers2

1

distinct/1 is a quite new predicate. It is only of relevance, if the incremental evaluation is of importance either because of infinite data or because (for some obscure reason) the exact order of answers is of relevance. OK, and maybe also because there are many redundant answers and the space to store them would be forbidding, but then a good setof/3 implementation might use a similar technique as well. In your case, you have just a data base of finitely many facts.

Since 19821, the classic predicate for your purpose is setof/3.

You did not give a minimal reproducible example. So I need to do some guessing. In any case, do trust the for printing.

city_part(City, CPart) :-
   setof(t, city_part0(City, CPart), _).

city_part0(City, part(Part, Name, Color, Num, X)) :-
   proj(Project, _A1, City),
   sppj(_A2, Part, Project, _A3),
   part(Part, Name, Color, Num, X).

You can avoid the intermediary predicate, but then the variable quantification will become cumbersome. I have given these variables already the names A1, A2, A3. These plus Project are only internal variables.

city_part(City, CPart) :-
   setof(t, A1^A2^A3^Project^
         (  CPart = part(Part, Name, Color, Num, X), 
            proj(Project, A1, City),
            sppj(A2, Part, Project, A3),
            part(Part, Name, Color, Num, X) 
         ), _).
false
  • 10,264
  • 13
  • 101
  • 209
0

As you wrote it, the goal part/5 that provides displayed values is unrelated to the conjunction you asked for in distinct/1. If I understand your problem correctly, most likely you should use distinct/2 instead. Try for instance

allpartsincity(City):-
    distinct(part(Part, Name, Color, Num, X), (proj(Project, _, City), sppj(_, Part, Project, _), part(Part, _, _, _, _))),
    format('~w ~w ~w ~w ~w ~n', [Part, Name, Color, Num, X]),
    fail
    ;
    true.
CapelliC
  • 59,646
  • 5
  • 47
  • 90
  • `distinct/1` is useless here, rather `setof(t,Var^G?0,[t])`, since the order of answers has here no relevance at all – false Feb 28 '20 at 11:13
  • @false: don't get what you mean, sorry... distinct doesn't use ordering, but memoizing, afaik. It's `setof(t,Var^G?0,[t])` the actual syntax? Have never seen it... What the `0` means ? – CapelliC Feb 28 '20 at 11:34
  • @false is right about `distinct/1` not working here, but I'm also not sure about the syntax for `setof(t,Var^G?0,[t])`. – vio Feb 28 '20 at 13:09
  • @vio: what about distinct/2, as I suggested? – CapelliC Feb 28 '20 at 13:14
  • @CapelliC, actually, I got that to work with a little bit of tweaking. Thanks! `part(Part, Name, Color, Num, X),` is still required, but also inserting it into the distinct clause worked! – vio Feb 28 '20 at 13:41