After reading the whole topic, I believe there is an implicit subject that was not touched on in this thread.
From your initial formulation:
I want to make a rule where I have three variables, Input, Compare, Output.
If the user supplies the Compare value, I want it to be run with that. If the user does
not supply a Compare, I want to set it.
Essentially, your Compare
variable represent the mode of the predicate.
Or in your own words, whether the predicate is running in forward or reverse mode.
Usually, in prolog, we qualify the mode of variables. In the documentation, you will see variables annotated with either +
, -
or ?
that respectively means input, output or both.
So to go back to your problem, you actually don’t need that third variable Compare
to specify the mode of your predicate.
You can use different instantiation pattern of your predicate to evaluate either in forward or backward mode:
?- odd(3, IsOdd). % call the predicate in forward mode, meaning: Is 3 odd ?
?- odd(X, 1). % call the predicate in backward mode, meaning: X is an odd number
Usually, forward mode is, well, straightforward to reason about and implement but you also need to ask yourself what it means to run in backward mode.
In your example, calling odd(X, 1)
means X is an odd number
. However, since there is an infinity of odd numbers, what would you like prolog to return here ?
Usually, prolog provides two type of solutions:
- iterate one solution at a time using backtracking. So calling
odd(X, 1)
would bind X to values like1
then3
then5
and so on infinitely on backtracking (although this limits the solution to positive integers only…) - delay the goal until X is ground. This is what you do when using clpfd or clpBNR or freeze.
PS: here is another lengthy reply of mine about the even/1
predicate : Fully understanding the "intricacies" of the Prolog code design process - #40 by kwon-young