Search code examples
listprolog

How to make list out of objects in Prolog?


I can add a single object to a list with this code and query:

makelist(A, B, C, X) :- append([1, 2, 3],A, X).

?- makelist(a, b, c, X).
X = [1, 2, 3|a].

However rather than the usual separator comma (,) there's a vertical line separator (|) and I cannot add another object to the same list:

makelist(A, B, C, X) :- append([1, 2, 3],A, X), append(X,B, X).

?- makelist(a, b, c, X).
false.

Solution

  • There are several misunderstandings. First, lists and their elements are confused which leads to the "dotted pair" that is |a]. Then, it seems that the role of variables is not clear to you.

    In the goal append([1,2,3],A,X) both A and X are supposed to be lists. However, you set A to a which is not a list. The problem behind is that append/3 accepts any term for the second argument. To see this, just look at its answers:

    ?- append([1,2,3],A,X).
    X = [1,2,3|A].
    

    So the A can be anything, but it should be rather only a list.

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

    Note that append/3 insists that the first argument is a list (or a partial list). Then once you have a bad list, you can no longer append it further. That is:

    ?- A = a, append([1,2,3],A,X), append(X, _, _).
       false.
    

    Note that I did not use your definition literally. Instead, I replaced certain arguments by _ since they cannot help.

    The second problem stems from the goal append(X, B, X). This goal, can only be true if B = []. Let's try this out:

    ?- append(X, B, X).
       X = [], B = []
    ;  X = [_A], B = []
    ;  X = [_A,_B], B = []
    ;  X = [_A,_B,_C], B = []
    ;  ... .
    

    And:

    ?- B = [_|_], append(X, B, X).
       loops.
    

    While there are many answers for X, B is always [].