To solve the space problem, we define all_different(L) in the following way:
all_different(L) => all_different(L,[]).
all_different([],Left) => true.
all_different([X|Right],Left) =>
outof(X,Left,Right),
all_different(Right,[X|Left]).
outof(X,Left,Right), var(X), {ins(X)} => true.
outof(X,Left,Right) =>
exclude_list(X,Left),exclude_list(X,Right).
For each variable X, let Left be the list of variables to
the left of X and Right be the list of variables to the
right of X. The call outof(X,Left,Right) holds
if X appears in neither Left nor Right. Instead of
generating disequality constraints between X and all the
variables in Left and Right, the call outof(X,Left,Right) suspends until X is instantiated. After X becomes an integer, the calls exclude_list(X,Left) and exclude_list(X,Right) to exclude X from the domains of the variables in
Left and Right, respectively.
There is a propagator outof(X,Left,Right) for each element X in the list, which takes constant space. Therefore, all_different(L) takes linear space in the size of L. Notice that the two lists Left and Right are not merged into one bigger list. Or, the constraint still takes quadratic space.