While the answer given by @Kay is spot-on as far as fixing the bug is concerned, it completely circumvents a much bigger issue: The code of occ1/4
is logically impure.
This may not appear very important to you right now,
but using impure code has several negative consequences:
- Impure code cannot be read declaratively, only procedurally.
- Debugging impure code is often tedious and pain-staking.
- Impure predicates are less "relational" than their pure counterparts.
- Logical impurity hampers code re-use.
- Because it is non-monotone, impure code is prone to lead to logically unsound answers, particularly when working with non-ground terms.
To show that these problems persisted in your code after having been "fixed" as suggested @Kay, let us consider the "corrected" code and some queries. First, here's the corrected code:
occ(K,L,N) :- N1=0, occ1(K,L,N1,N).
occ1(_,[],N1,N) :- N=N1.
occ1(K,L,N1,N) :-
L=[X|L1],
( K=X -> N2 is N1+1, occ1(K,L1,N2,N) ; occ1(K,L1,N1,N) ).
Here's the query you gave in your question:
?- occ(a,[b,a,b,c,a,d,a],N).
N = 3 ;
false.
Okay! What if we write the query differently?
?- A=a,B=b,C=c,D=d, occ(a,[B,A,B,C,A,D,A],N).
A = a, B = b, C = c, D = d, N = 3 ;
false.
Okay! What if we reorder goals? Logical conjunction should be commutative...
?- occ(a,[B,A,B,C,A,D,A],N), A=a,B=b,C=c,D=d.
false.
Fail! It seemed that occ1/4
is fine, but now we get an answer that is logically unsound.
This can be avoided by using logically pure code:
Look at the pure and monotone code I gave in my answer to the related question "Prolog - count repititions in list (sic)".