I'm experimenting with Prolog and tried to make my own "if-then-else
" method, so that I don't use the -> ;
method, for experimenting's sake.
My goal is to make it so that there can be nested ifs and elses in my code if required.
Thus far I have got this:
ifthenelse(_, G, G):- G. %no matter the condition, the goals are the same
ifthenelse(true,G,_):- G. %if
ifthenelse(false,_,G):- G. %else
I think my way hardly seems correct. How can I make my own ifthenelse/3
properly?
Thank you
Preface: What you have implemented is, in an important way, a lot better than the built-in construct you mentioned. I will discuss this point in more detail below.
Regarding the literal question: I think you are quite close already, since you can already nest this to some extent:
?- ifthenelse(C1, ifthenelse(C2,X=1,X=2), X=3). C1 = C2, C2 = true, X = 1 ; C1 = true, C2 = false, X = 2 ; C1 = false, X = 3.
What now remains is to make it nestable in the condition. For this, you need a way to reify the outcome of conditions, that is, to turn the truth value into a Prolog term that you can reason about symbolically.
See if_/3
for more information: Indexing dif/2
A key property this construct preserves is called logical-purity. In particular, do not erroneously commit to one branch if both are logically possible!
Note on purity: From a declarative point of view, what you have implemented is very nice and has a clear logical interpretation. Taking for example the last two clauses, we can read ifthenelse(C,G1,G2)
as: If C
is true
, then the predicate holds if G1
holds. If C
is false
, then it holds if G2
holds. Perfectly fine. A semantic "if...then" is not in any way problematic; in fact, every single Horn clause can be read in this way, as an implication from right to left.
In contrast, the built-in construct you mention lacks such a declarative reading in general. For example:
?- ( ( X = 1 ; X = 2 ) -> true ; true ). X = 1.
But on the other hand:
?- X = 2, ( ( X = 1 ; X = 2 ) -> true ; true ). X = 2.
So adding a constraint has led to a new solution. A classical logician's nightmare.
Your construct avoids such problems, because it does not prematurely commit to any particular branch. This yields a much more versatile predicate that can also be used in other directions. For example, see that all possible solutions are correctly generated:
?- ifthenelse(C, true, true). true ; C = true ; C = false.
So, I highly encourage your way of formulating this: As you have made perfectly clear, it's your own 'if-then-else', and you are using only pure monotonic constructs to express it.
On a psychological note, I generally prefer to give more room to pure declarative constructs and I added this section only because the comments expressed genuine interest in these aspects.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With