Рассмотрим, что я пробовал:
dif_to_orto(A, B, C) :-
( dif(A, B)
; dif(A, C)
).
Хотя это определение прекрасно с декларативной точки зрения, оно содержит много избыточности. Думать о:
?- dif_to_orto(A, B, C), A = 1, B = 2, C = 2.
A = 1, B = 2, C = 2
; A = 1, B = 2, C = 2. % unexpected redundant solution
И даже не в этом случае:
?- dif_to_orto(A, B, C), A = 1, B = 2, C = 3.
A = 1, B = 2, C = 3
; A = 1, B = 2, C = 3. % unexpected redundant solution
По крайней мере, здесь случай без излишеств...
?- dif_to_orto(A, B, C), A = 1, B = 2, C = 1.
A = 1, B = 2, C = 1
; false. % unexpected inefficient leftover choicepoint
... но с оставшейся точкой выбора, которая тратит ресурсы.
Редко бывают случаи, когда это определение эффективно:
?- dif_to_orto(A, B, C), A = 1, B = 1, C = 2.
A = 1, B = 1, C = 2.
Кроме того, тот факт, что самый общий запрос дает два ответа, кажется мне очень неэффективным:
?- dif_to_orto(A, B, C).
dif:dif(A,B)
; dif:dif(A,C).
... что создает также следующую избыточность:
?- dif_to_orto(1, B, B).
dif:dif(1,B)
; dif:dif(1,B). % unexpected redundant answer
Одного dif/2
было бы достаточно!
Есть ли способ избежать всей этой избыточности и неэффективности?