I'm learning Prolog. I was experimenting with an elemindex
predicate, with the form elemindex(element, index, list)
, such that, for instance, elemindex(1,0,[1,2,3,1]).
or elemindex(3,0,[1,2,3,1]).
.
Due to instantiation restraints, I ended up with this:
elemindex(E, 0, [E|_]).
elemindex(E, s(M), [_|L]) :- elemindex(E,M,L).
However, if I query ?- elemindex(1,N,[1,2,3,1]).
, as in my example, Prolog responds:
N = 0
N = s(s(s(0)))
yes
This is certainly working, but I would like s(s(s(0)))
to at least display as 3
. Furthermore, I cannot execute queries like ?- elemindex(E, 3, [1,2,3,4]).
, but changing the code to use N is M+1
makes me lose the ability to evaluate the 1st kind of query.
So, my question is 2-fold:
s(s(s(0)))
to display as 3
in my results?elemindex
such that I can query for the element and the index?#=/2
is part of the CLPFD library, which is what you'd use to "reason" over integers. The is/2
operator is designed to evaluate a completely known expression, so requires that the 2nd argument be completely bound so it's immediately evaluable. #=/2
doesn't have that restriction. You won't get the instantiation error, and Prolog will attempt to solve for the variables. Do a google search on "Prolog clpfd".
Here's how it works with your code:
elemindex(E, 0, [E|_]).
elemindex(E, Index, [_|L]) :-
Index #= N + 1,
N #>= 0,
elemindex(E, N, L).
Then queries:
| ?- elemindex(1,N,[1,2,3,1]).
N = 0 ? a
N = 3
no
| ?- elemindex(E, 3, [1,2,3,4]).
E = 4 ? a
no
| ?-