Why do these two prolog sentences have different outputs?

I've recently started learning Prolog and there's something that I don't understand.

Why do these two sentences gives different outputs?
I understand that everything at the left of an [ | ] expression must be the head of the list and at the right side we've the tail of the list.
I suspect it must be trivial but at the end I don't get why as in the first case the second one doesn't unify both parts as one single list.

?- X = [2|[1]].
   X = [2,1].

?- X = [[1]|2].
   X = [[1]|2].

Upvotes: 1

Views: 58

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476659

Well thesecond one is not a list, or at least not what the "Prolog community" considers a list.

If we take a look at what you wrote, the first expression can be seen as something similar to:

+-------+
|  cons |
+---+---+  +-------+
| o | o--->|  cons |
+-|-+---+  +---+---+
  v        | o | o---> nil
  2        +-|-+---+
             v
             1

So this is a list: you basically construct a "cons", with as head 2, and as tail another list. Note that the head of the list is an element, whereas the tail of the list, is a list with the remaining elements.

In your second example, you probably made a typo, probably you have written:

?- X = [[1]|2].
X = [[1]|2].

In that case the "list" looks like:

+-------+
|  cons |
+---+---+
| o | o---> 2
+-|-+---+
  v        
+-------+
|  cons |
+---+---+
| o | o---> []
+-|-+---+
  v
  1

Note that this is not really a list: the head of the cons, is an element, and of course such element can be a list (since we can construct lists of lists, etc.), but the tail here, is simply an element.

This means that one can not apply syntactical sugar, and thus replace this with something like [1,2]. Note that [1] is actually syntactical sugar for [1|[]], and [2,1] is syntactical sugar for [2|[1|[]]] (as wee see in the first image). But [[1]|2] has no such syntactical sugar equivalent.

Most Prolog interpreters allow you to write lists in a canonical way, for example in GNU Prolog:

| ?- write_canonical([1]).
'.'(1,[])

(1 ms) yes
| ?- write_canonical([1,2]).
'.'(1,'.'(2,[]))

(1 ms) yes
| ?- write_canonical([[1]|2]).
'.'('.'(1,[]),2)

yes

Here we se thus that the "cons" function is the dot '.' that is a functor).

Upvotes: 2

Related Questions