Search code examples
prologiso-prolog

Prolog - unusual cons syntax for lists


I have come across an unfamiliar bit of Prolog syntax in Lee Naish's paper Higher-order logic programming in Prolog. Here is the first code sample from the paper:

% insertion sort (simple version)
isort([], []).
isort(A.As, Bs) :-
    isort(As, Bs1),
    isort(A, Bs1, Bs).

% insert number into sorted list
insert(N, [], [N]).
insert(N, H.L, N.H.L) :-
    N =< H.
insert(N, H.LO, H.L) :-
    N > H,
    insert(N, LO, L).

My confusion is with A.As in isort(A.As, Bs) :-. From the context, it appears to be an alternate cons syntax for lists, the equivalent of isort([A|As], Bs) :-.

As well N.H.L appears to be a more convenient way to say [N|[H|L]].

But SWI Prolog won't accept this unusual syntax (unless I'm doing something wrong).

Does anyone recognize it? is my hypothesis correct? Which Prolog interpreter accepts that as valid syntax?


Solution

  • The dot operator was used for lists in the very first Prolog system of 1972, written in Algol-W, sometimes called Prolog 0. It is inspired by similar notation in LISP systems. The following exemple is from the paper The birth of Prolog by Alain Colmerauer and Philippe Roussel – the very creators of Prolog.

    +ELEMENT(*X, *X.*Y).
    +ELEMENT(*X, *Y.*Z) -ELEMENT(*X, *Z).
    

    At that time, [] used to be NIL. All remaining the same in the next version Prolog I written in Fortran by Battani & Meloni.

    Then DECsystem 10 Prolog used cases to distinguish atoms and variables and introduced the square bracket notation replacing nil and X.Xs with [] and [X,..Xs] which in later versions of DECsystem 10 received [X|Xs] as an alternative. In ISO Prolog, there is only [X|Xs], .(X,Xs), and as canonical syntax '.'(X,Xs).

    Please note that the dot has many different rôles in ISO Prolog. It serves already as

    • end token when followed by a % or a layout character like SPACE, NEWLINE, TAB.

    • decimal point in a floating point number, like 3.14159

    • graphic token char forming graphic tokens as =..

    So if you are now declaring . as an infix operator, you have to be very careful. Both with what you write and what Prolog systems will read. A single additional space can change the meaning of a term. Consider two lists of numbers in both notations:

    [1,2.3,4]. [5].
    1 .2.3.4.[]. 5.[].
    

    Please note that you have to add a space after 1. In this context, an additional white space in front of a number may change the meaning of your terms. Like so:

    [1|2.3]. [4]. 5. [].
    1 .2.3. 4.[]. 5. [].
    

    Here is another example which might be even more convincing:

    [1,-2].
    1.(-2).[].
    

    Negative numbers require round brackets within dot-lists.

    Today, there is only YAP and XSB left that still offer infix . by default – and they do it differently. And XSB does not even recognize above dot syntax: you need round brackets around some of the nonnegative numbers.

    You wrote that N.H.L appears to be a more convenient way to say [N|[H|L]]. There is a simple rule-of-thumb to simplify such expressions in ISO Prolog: Whenever you see within a list the tokens | and [ immediately after each other, you can replace them by , (and remove the corresponding ] on the right side). So you can now write: [N,H|L] which does not look that bad.

    You can use that rule also in the other direction. If we have a list [1,2,3,4,5] we can use | as a "razor blade" like so: [1,2,3|[4,5]].


    Another remark, since you are reading Naish's paper: In the meantime, it is well understood that only call/N is needed! And ISO Prolog supports call/1, call/2 up to call/8.