Next contestant to the code beauty pageant!-)
This answer shows a refactored variation of code shown in
a previous answer. It uses reified conjunction and disjunction:
and_(P_1,Q_1) :-
and_t(P_1,Q_1,true).
or_(P_1,Q_1) :-
or_t(P_1,Q_1,true).
and_t(P_1,Q_1,Truth) :-
if_(P_1, call(Q_1,Truth), Truth=false).
or_t(P_1,Q_1,Truth) :-
if_(P_1, Truth=true, call(Q_1,Truth)).
Note the two versions for both "and" and "or"; the ones with suffix _t
have an extra argument for the truth value, the ones without the suffix do not and assume that Truth=true
should hold.
Based on and_t/3
and on reified term inequality predicate dif/3
, we define nonmember_t/3
:
nonmember_t(X,Ys,Truth) :-
list_nonmember_t(Ys,X,Truth).
list_nonmember_t([] ,_, true).
list_nonmember_t([Y|Ys],X,Truth) :-
and_t(dif(X,Y), list_nonmember_t(Ys,X), Truth).
Now, let's define some_absent_t/3
, different_t/3
and different/2
, like so:
some_absent_t([] ,_ ,false).
some_absent_t([X|Xs],Ys,Truth) :-
or_t(nonmember_t(X,Ys), some_absent_t(Xs,Ys), Truth).
different_t(Xs,Ys,Truth) :-
or_t(some_absent_t(Xs,Ys),
some_absent_t(Ys,Xs),
Truth).
different(Xs,Ys) :-
different_t(Xs,Ys,true).
Does it still run?
?- different([A,B],[X,Y]).
A=X , B=X , dif(Y,X)
; A=X , dif(B,X), dif(B,Y)
; A=Y , B=Y , dif(Y,X), dif(Y,X)
; A=Y , dif(B,X), dif(B,Y), dif(Y,X)
; dif(A,X), dif(A,Y). % same result as before
?- different([4,2,3],[2,3,1]), different([1,2,3],[4,3,1]),
different([1,4,3],[2,3,1]), different([1,2,3],[2,4,1]),
different([1,2,4],[2,3,1]), different([1,2,3],[2,3,4]).
true. % same result as before
Looks alright!
All in all, not a huge improvement over existing answers, but IMO somewhat more readable code, and a reified version of different/2
as an added bonus!
different([a,b],Y).
, it gives:Y = [_G122], dif(_G122, a) ;
, but thedif(_G122,a);
is not necessary: even if it is equal toa
, that's not a problem. Of course if one queries fordifferent([a,b],[Y])
, one getsdif(Y,a)
,dif(Y,b)
anddif(Y,b),dif(Y,a)
, but still that's not necessary. – Londalondon