OP implemented two drive-style predicates for calculating Hamming distances ( hamm/4 and hamm2/4 ), but was not sure which one made more sense.
Let's read the query puzzled by the OP: "Is there an X such that the distance (a, X) is 1?" Here are the “answers” Prolog gives:
?- hamm(a,X,0,1). false. % wrong: should succeed conditionally ?- hamm2(a,X,0,1). % wrong: should succeed, but not unconditionally true.
From a logical point of view, both implementations do not work correctly in the above test. Let's do some durability tests:
?- hamm(a,X,0,1),X=a. % right false. ?- hamm(a,X,0,1),X=b. % wrong: should succeed as distance(a,b) is 1 false. ?- hamm2(a,X,0,1),X=a. % wrong: should fail as distance(a,a) is 0 X = a. ?- hamm2(a,X,0,1),X=b. % right X = b.
Note that in previous hamm/4 requests, failure fails if hamm2/4 and vice versa. Thus, both are half-right / half-wrong, and neither are stable.
What can be done?
Based on if_/3 and (=)/3 provided by @false in this answer , I implemented the following clean code for the hamm3/4 predicate:
:- use_module(library(clpfd)). hamm3(A,B,V0,V) :- if_(A = B, V0 = V, V
Now repeat the above queries with hamm3/4 :
?- hamm3(a,X,0,1). dif(X,a). ?- hamm3(a,X,0,1),X=a. false. ?- hamm3(a,X,0,1),X=b. X = b.
It works! Finally, let me ask you the most general query to see the entire hamm3/4 solution set:
?- hamm3(A,B,N0,N). A = B, N0 = N ; dif(A,B), N0+1