I offered the following clpfd-based code for the recent question Segregating Lists in Prolog:
list_evens_odds([],[],[]).
list_evens_odds([X|Xs],[X|Es],Os) :-
X mod 2 #= 0,
list_evens_odds(Xs,Es,Os).
list_evens_odds([X|Xs],Es,[X|Os]) :-
X mod 2 #= 1,
list_evens_odds(Xs,Es,Os).
It is concise and pure, but can leave behind many unnecessary choice-points. Consider:
?- list_evens_odds([1,2,3,4,5,6,7],Es,Os).
Above query leaves behind a useless choice-point for every non-odd item in [1,2,3,4,5,6,7]
.
Alternative implementation
Using the reification technique demonstrated by @false in Prolog union for A U B U C can reduce the number of unnecessary choice-points. The implementation could change to:
list_evens_odds([],[],[]).
list_evens_odds([X|Xs],Es,Os) :-
if_(#<=>(X mod 2 #= 0), (Es=[X|Es0],Os= Os0),
(Es= Es0, Os=[X|Os0])),
list_evens_odds(Xs,Es0,Os0).
To directly interact with clpfd-reification the implementation of if_/3
could be adapted like this:
if_( C_1, Then_0, Else_0) :-
call(C_1,Truth01),
indomain(Truth01),
( Truth01 == 1 -> Then_0 ; Truth01 == 0, Else_0 ).
Of course, (=)/3
would also need to be adapted to this convention.
The bottom line
So I wonder: Is using 0
and 1
as truth-values instead of false
and true
a good idea?
Am I missing problems along that road? Help, please! Thank you in advance!