Prolog 中的列表被实现为函子的链表。如果你写一个像[a, b, c, d] 这样的列表。它实际上看起来像:
+-------+
| (|)/2 |
+---+---+ +-------+
| o | o---->| (|)/2 |
+-|-+---+ +---+---+ +-------+
v | o | o---->| (|)/2 |
a +-|-+---+ +---+---+ +-------+
v | o | o---->| (|)/2 |
b +-|-+---+ +---+---+
v | o | o----> []
c +-|-+---+
v
d
或使用 Prolog 表示法 [a | [b | c | [d | [] ] ] ]。逗号分隔的列表是语法糖:如果您写[a, b, c, d],Prolog 解释器会将其转换为上述表示。
由于[b, c, d] 等于:
[ b | [ c | [ d | [] ] ] ]
因此[ a | [b, c, d] ] 等于
[a | [b | c | [d | [] ] ] ]
但列表[X, Y] 正好等于
[X, Y] == [ X | [ Y | [] ] ]
或以结构方式:
+-------+
| (|)/2 |
+---+---+ +-------+
| o | o---->| (|)/2 |
+-|-+---+ +---+---+
v | o | o----> []
X +-|-+---+
v
Y
如果我们然后将其与[a | [b | c | [d | [] ] ] ] 匹配,这意味着可以匹配“外部”外壳,因此X = a,然后是Y = b 和[] = [ c | [ d | [] ] ]。最后一部分不匹配,因此它返回false。 X 和 Y 因此不是问题。问题是[]是一个常数,和代表[ c | [d] ]的函子不匹配。
如果我们例如统一[ X | Y ] == [a, b, c, d],我们会得到:
?- [ X | Y ] = [a, b, c, d].
X = a,
Y = [b, c, d].
总而言之,可以说| 本身“什么都不做”。它是一个仿函数,就像f(1, 2)。在 Lisp 中,他们为此使用 cons [wiki],并为空列表使用 nil。所以[1, 4, 2, 5] 在 Lisp 中看起来像 cons 1 (cons 4 (cons 2 (cons 5 nil))),或者在 Prolog 中看起来像 cons(1, cons(4, cons(2, cons(5, nil))))。只是写起来有点麻烦。事实上,逗号分隔符号更像是“魔法”部分。 Prolog 只是对列表执行统一,就像它对其他仿函数和常量所做的一样。