In Prolog, I would like to implement a trivial logical induction predicate i as (1):
i(0).
i(N) :- i(N-1).
or (2):
i(0).
i(N+1) :- i(N).
But this doesn't work; with (1), query i(3). causes a stack overflow; with (2), i(3). returns false.
Instead, I have to do (3):
i(0).
i(N) :- M is N-1, i(M).
Naively, the difference between (3) and (1) seems like a trivial syntactic shift, and declaring intermediate variables feels like a hassle in bigger programs. What's the reason behind the Prolog compiler rejecting (1) and (2), does a work-around exist, and why do (1) and (2) behave differently?
Surprisingly, it isn't a trivial syntactic shift.
N-1in Python is always arithmetic; you can replace5-1with4and"cat"-1is an error.In Prolog dash is not arithmetic, it's a term connecting Left/Right with a dash. You can write
"cat"-1("cat dash one") to pair two things up and pass them around together, and people do:So people wanted a way to wedge math into a logical relation language, and came up with a predicate which knows how to do calculation on terms with the names + - / * and so on. A predicate like
math_evaluate(Result, Term)and if you had it you could write it likeResult math_evaluate N-1so it looks neater. That math_evaluate predicate isis(Result, Term):which you can write
Result is N-1in a similar way that you can rewrite-(N,1)asN - 1.