As noted in another StackOverflow answer that I can't seem to find anymore, this pattern emerges frequently in practical Prolog code:
pred(X) :-
guard(X),
...
pred(X) :-
\+ guard(X),
...
and many people try to condense this to
pred(X) :-
(guard(X) ->
...
;
...).
However as we all know, the arrow structure destroys choice points and isn't logical.
In Ulrich Neumerkel's and Stefan Kral's Indexing dif/2, a predicate called if_/3
is proposed that is monotonic and logical, however in the paper they mention another construct which caught my eye: *->
.
The *->
construct functions exactly like the unsugared guard clause example above, and thus it seems perfect for my uses as I don't want to have a reified condition which is required by if_/3
and I don't care about extra choice points that much. If I'm not mistaken (edit: I am), it offers the same semantics as if_/3
but without the requirement of adding the "reification" to the condition predicate.
However in the SWI documentation for it, it claims that "this construct is rarely used," which seems weird to me. *->
seems to me like it's strictly better than ->
when you're trying to do pure logical programming. Is there any reason to avoid this structure, or is there an even better alternative to the entire guard clause / negated guard clause pattern?
if_/3
. You are mistaken. Please refer to 2 The declarative limits of Prolog’s if-then-else, last paragraph: Even the “soft cut”-versionsif/3
and(*->)/2
of SICStus and SWI respectively, exhibit the same problems as Prolog’s unsound negation. – Ambulatoryif/3
(not efficient as it executes the guard twice):if(G_0, Then_0, _) :- G_0, Then_0. if(G_0, _, Else_0) :- \+ G_0, Else_0.
You see the\+
? It's full of impurity! – Ambulatory