We start with the name of the predicate.
Why do you use an imperative to denote a relation? A good Prolog program is usable in all directions, whereas an imperative always suggests a particular direction or mode of use. Therefore, choose a declarative name and aim for generality and logical-purity.
Next, what about the most general query:
?- compress(Ls, Cs).
ERROR: Out of local stack
Not very nice! We expect this to yield at least a few answers.
What if we use iterative deepening:
?- length(Ls, _), compress(Ls, Cs).
Ls = Cs, Cs = [] ;
Ls = Cs, Cs = [_G841] ;
Ls = [_G841, _G841],
Cs = [_G841] ;
Ls = [_G841, _G841, _G841],
Cs = [_G841] .
Hm! Quite a few answers are missing! What about the case where the elements are different? As you already intuitively expect, it is the use of impure predicates that leads to such effects.
Therefore, use prolog-dif, i.e., dif/2
, to denote that two terms are different. It's usable in all directions!
Moreover, DCGs (dcg) are often useful when describing lists.
So, in total, what about this:
compression([]) --> [].
compression([L|Ls]) --> [L], compression_(Ls, L).
compression_([], _) --> [].
compression_([X|Xs], L) -->
( { X = L },
compression_(Xs, L)
; { dif(X, L) },
[X],
compression_(Xs, X)
).
We use the interface predicate phrase/2
to work with the DCG.
Usage examples:
?- phrase(compression(Ls), Cs).
Ls = Cs, Cs = [] ;
Ls = Cs, Cs = [_G815] ;
Ls = [_G815, _G815],
Cs = [_G815] .
?- length(Ls, _), phrase(compression(Ls), Cs).
Ls = Cs, Cs = [] ;
Ls = Cs, Cs = [_G865] ;
Ls = [_G865, _G865],
Cs = [_G865] ;
Ls = Cs, Cs = [_G1111, _G1114],
dif(_G1114, _G1111) .
Take it from here! Improve determinism, find an even better name etc.