# Why no if-but-not-else construct?

I often find myself using the `(P -> Q; true)` formulation, when I need to do an extra check or take an extra action but only when a certain precondition is true; when it isn’t, the clause can proceed as it would otherwise. Why isn’t there a built-in operator or predicate that does this? Perhaps something that binds tighter than `,/2`, like say:

``````:- op(800, xfy, ?).

% Whenever P succeeds, then Q must succeed, but \+P is fine
P ? Q :- P *-> Q; true.

% Match *or* generate "(At)" in text, when At is an atom
parenthesized_atom(At) -->
`(`,
{ground(At) ? atom_codes(At,AC)},
string(AC),
`)`,
{atom_codes(At,AC)}.
``````

Note that this isn’t a “how can I do this, please” - I have a number of ways I can implement this, and it’s not all that cumbersome (and more to the point, I want to make sure that I am writing idiomatic Prolog). It’s more of a “why was Prolog designed this way?” combined with some amount of “are there hidden pitfalls to doing this kind of thing that I’m not aware of?”

I don’t know the reason (I have a couple of theories), but I do know that Logtalk’s linter complains about `(P->Q)` but doesn’t complain about `(P->Q;fail)`.

Paulo Moura (author of Logtalk) doesn’t seem to be in this discussion group, but maybe somebody knows the reason?

I think the reason is that from a logical point of view, `P -> Q` is seen as (in logic) `P implies Q`.

Now, when `P implies Q` (in logic), you are not saying anything at all about what happens if `not P` (you could still have `Q` even if `not P`), and therefore I think it would be sensible from this point of view to always specify what happens if `not P` when you are implementing a programming language.

Almost every time I use `(P->Q;true)`, `Q` is something “impure”, such as a print statement – I have more examples of `(P->true;Q)`.

So, maybe it’s a Good Thing that there’s no short-cut for `(P->Q;true)` because it’s a “code smell”.

Yes, I don’t often need this construct.

On the other hand `(P->true;Q)` is much more common because `P` unifies what needs to be unified.

`(bad_input(X)->throw(error(bad_input(X), _));true)` … this is similar to must_be/2 or domain_error/2.
Although there’s been a long discussion about failure vs throwing an exception.

Another useful case: In a DCG: `({some_test(X)}->[X];[])`.

Ooh fun, I’ll play! Let’s see. I’ll mark the `true`s that get executed with `%%%%`

``````?- ((true->true),true;true).
%    %%%%  %%%%  %%%%^ Choice point here, this isn't a ->; construct
?- ((true->true);true).
%    %%%%  %%%%        No choice points, the -> cuts the ; choice
?- ((true->true);true;(true->true)).
%    %%%%  %%%%      ^ Choice point here, the second ; doesn't get cut
?- (((true->true);true);(true->true)).
%     %%%%  %%%%       ^ Choice point here, syntactically equivalent to the above
``````

I think these are correct. Not so sure about #3, but I’m pretty sure the precedence rules group on the left `;/2`, so only that one gets cut by the `->/2`.

Well? How’d I do?

Ah! I had my precedence rules for `;/2` backward. I always have trouble with those… which is why `write_canonical/1` is my best friend