If your intention is to define f(A,X)
such that g(X)
should be evaluated whether or not c
fails, then either:
- You could encode this using implication (
->
) and/or disjunction (;
), or
f(A,X)
doesn't need to be defined in terms of c
. This assumes c
has no side-effects (e.g., asserting database facts using assert
, or printing IO to a stream) which alter the environment and which cannot be undone on failure of c
, in which case the first option is preferable.
There are several alternatives for using disjunction, such as:
f(A,X) :- ((a, b, c) ; (a, b)), g(X).
This definition (above) doesn't depend on c
at all, but it will always execute c
(as long as a
and b
succeed). The disjunction (;
) allows PROLOG to backtrack to try executing a, b
again if c
failed at all, and to continue onto g(X)
. Note that this is equivalent to:
f(A,X) :- a, b, c, g(X).
f(A,X) :- a, b, g(X).
In order for PROLOG not to backtrack to evaluate f(A,X)
twice because of the second (identical) head predicate f(A,X)
for every evaluation, you may choose to place a cut (!
), if your implementation supports it, immediately after the c
subgoal in the first clause. The cut is placed after c
because we don't want the interpreter to commit to that choice of f(A,X)
clause if c
had failed, instead, we want the interpreter to fail out of this clause and to try the next one, to effectively ignore c
and to continue processing g(X)
.
Also note that this solution relies on a
and b
having no side-effects, because when c
fails, a
and b
are executed again. If all a
, b
, and c
have side effects, you can try using implication:
f(A,X) :- a, b, (c -> g(X) ; g(X)).
This will also effectively always execute g(X)
whether c
fails or not, and will not execute a
and b
again if c
fails. This single-clause definition will also not leave a choice-point like the previous suggestion.