Search code examples
prologswi-prolog

Why doesn't the desugared "." functor syntax for lists work the same as []?


I'm reading Programming in Prolog (5th Edition), and in Chapter 3 the book introduces lists with this syntax:

The empty list is written as [] ... The head and tail of a list are components of the functor named ".", which is the dot (called the period or full stop). Thus, the list consisting of one element "a" is ".(a,[])", ...

the list consisting of the atoms a, b and c is written .(a,.(b,.(c,[]))), ...

Then on the next page it introduces the square bracket notation as if it is a sugared equivalent to the previous syntax:

As the dot notation is often awkward for writing complicated lists, there is another syntax that can be used for writing lists in a Prolog program. This list notation consists of the elements of the list separated by commas, and the whole list is enclosed in square brackets. For example, the above lists can be written in the list notation as [a] and [a,b,c].

The page after that introduces the vertical bar syntax [X|Y] for matching on lists' heads/tails.

Why is it then, if I write these facts:

a([1,2,3]).
b(.(1,.(2,.(3,[])))).

This works:

?- a([X|Y]).
X = 1,
Y = [2, 3].

But not this?

?- b([X|Y]).
ERROR: Type error: `dict' expected, found `3' (an integer)
ERROR: In:
ERROR:   [11] throw(error(type_error(dict,3),_7636))
ERROR:    [9] '$dicts':'.'(3,[],_7676) at /usr/lib/swi-prolog/boot/dicts.pl:46
ERROR:    [8] b([_7704|_7706]) at /home/abe/code/programming_in_prolog/ch03/.scratch.pl:2
ERROR:    [7] <user>
ERROR: 
ERROR: Note: some frames are missing due to last-call optimization.
ERROR: Re-run your program in debug mode (:- debug.) to get more detail.

Edit: this attempt doesn't work either:

?- b(.(X,Y)).
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR:   [11] throw(error(instantiation_error,_7856))
ERROR:    [9] '$dicts':'.'(_7886,_7888,_7890) at /usr/lib/swi-prolog/boot/dicts.pl:46
ERROR:    [8] '<meta-call>'(user:(...,...)) <foreign>
ERROR:    [7] <user>
ERROR: 
ERROR: Note: some frames are missing due to last-call optimization.
ERROR: Re-run your program in debug mode (:- debug.) to get more detail.

Solution

  • After ver.7, you should write this unwieldy syntax:

    ?- [user].
    |: b('[|]'(1,'[|]'(2,'[|]'(3,[])))).
    |: ^D% user://1 compiled 0.01 sec, 1 clauses
    true.
    
    ?- b([X|Y]).
    X = 1,
    Y = [2, 3].
    
    

    This because, in short, the dot notation has been 'coopted' to support dictionary accessors in functional notation, for instance

    ?- write(_{a:1}.a).
    1
    true.
    

    See this doc for details.

    The whole section 5 of the manual is about SWI-prolog syntax changes WRT ISO prolog standard.