Using Xs\Ys for difference list results in compile error

I am reading “the art of Prolog” by Sterling and Shapiro and is stuck on chapter 15.1 ‘Difference-lists’. In short the use of Xs\Ys for a difference-list does not compile as expected. I tried compiling both from swipl and emacs, and both fails.
I noticed that help(flatten). specifically mentions difference lists, so what am I doing wrong?

I’m using: SWI-Prolog version 9.2.8 for x86_64-darwin, and sweepl (threaded, 64 bits, version 9.2.6) for emacs

I want the code to: implement difference-lists

But what I’m getting is: compile error.

?- [flatten_dl].
ERROR: /Users/neo/Library/Mobile Documents/com~apple~CloudDocs/prolog/the_art/flatten_dl.pl:20:12: Syntax error: Operator expected
ERROR: /Users/neo/Library/Mobile Documents/com~apple~CloudDocs/prolog/the_art/flatten_dl.pl:27:19: Syntax error: Operator expected
ERROR: /Users/neo/Library/Mobile Documents/com~apple~CloudDocs/prolog/the_art/flatten_dl.pl:29:20: Syntax error: Operator expected
ERROR: /Users/neo/Library/Mobile Documents/com~apple~CloudDocs/prolog/the_art/flatten_dl.pl:32:19: Syntax error: Operator expected
ERROR: /Users/neo/Library/Mobile Documents/com~apple~CloudDocs/prolog/the_art/flatten_dl.pl:35:13: Syntax error: Operator expected
true.

My code looks like this:

%program 15.2
%append_dl(As,Bs,Cs) :- The difference-list Cs is the result of appending Bs to As, where As and Bs are compatible difference-lists.
append_dl(Xs\Ys,Ys\Zs,Xs\Zs).

% program 15.2
%flatten(Xs,Ys) :-
%Ys is the flattened list containing the elements in Xs.
%@
flatten(Xs,Ys) :-
    flatten_dl(Xs,Ys\[]).

flatten_dl([X|Xs],Ys\Zs) :-
    flatten_dl(X,Ys\Ys1),
    flatten_dl(Xs,Ys1\Zs).
flatten_dl(X,[X|Xs]\Xs) :-
    constant(X),
    X\=[].
flatten([],Xs\Xs).

constant(X) :- \+ var(X).
1 Like

Can’t use that backslash character, it seems:

?- X = A\B.
ERROR: Syntax error: Operator expected
ERROR: X = 
ERROR: ** here **
ERROR: A\B . 

?- X = A/B.
X = A/B.

If you want to just move on, replace every “X\Y” with “X, Y”. For example, instead of writing:

flatten_dl(Xs, Ys\[]).

write:

flatten_dl(Xs, Ys, []).

Do this consistently throughout your program.

Your original code should have worked, however. I wonder what is the issue, exactly. The \ is defined as an operator…

This notation, X\Y, is not some special Prolog syntax, this is a term \(X, Y). In order for X\Y to be correctly parsed you need to define \ as a binary operator. Currently it is only defined as a unary operator. See the docs on operators. If I add the following on the top of the program you show:

:- op(400, yfx, (\)).

then the syntax errors are gone and there are other warnings instead.

However, modern Prolog code seems to use separate arguments to represent the two terms that comprise a difference list. One example in the standard library is findall/4. The third and fourth argument are the “list” and the “tail” that in “The Art of Prolog” would have been written as Bag\Tail I assume.

“The Art of Prolog” is a good book but sadly a bit outdated to enjoy without help from others.

2 Likes

Thank you, Boris. Adding the :- op(400, yfx, (\)). did the trick.

%test
 flatten_dl([1,2,[2,3,4]],Ys\[]).
% Ys = [1,2,2,3,4]