In the example given, reverse1
isn't using true difference list, but is just a different representation of reverse2
. They both use the same variables in the same way. reverse
uses a -
functor to attach them and reverse2
maintains them as separate parameters. But that's all that's different between the two. The algorithm behaviors are the same.
A real difference list is a list structure with a "hole" in it, like X-T
in which T
is not instantiated (until a later point in time perhaps), and X
contains T
(e.g., [a,b,c|T]-T
). The -
functor in this associates the "exposed" uninstantiated variable with the structure that contains it.
A popular and simple example is an implementation of append
using difference lists. A traditional, recursive implementation of append
might look like this:
append([], Ys, Ys).
append([X|Xs], Ys, [X|Zs]) :- append(Xs, Ys, Zs).
Simple enough, and execution time is proportional to the length of the first list.
Using difference lists, you can implement an append
as follows:
append(A-B, B-C, A-C).
That's all you need to append lists using difference lists. No recursion or anything else. Execution time is O(1)
independent of the length of the list. Here's an example execution:
append([1,2,3|T]-T, [4,5,6|W]-W, DL).
Yields:
DL = [1,2,3,4,5,6|W]-W
T = [4,5,6|W]
You can get to the concrete answer by "filling" the hole with an empty list in the last parameter:
append([1,2,3|T]-T, [4,5,6|W]-W, L-[]).
You get:
L = [1,2,3,4,5,6]
T = [4,5,6]
W = []