Prolog-统一两个有/无变量的列表

时间:2018-10-29 13:59:10

标签: list variables prolog unification

此Prolog代码返回:

?- [a,b,c,d]  =  [a|[b,c,d]].

true

和这个

?- [X,Y] = [a|[b,c,d]].

返回假。

我不完全理解[X, Y]为何为假。跟踪在这里没有帮助。我希望以下任务能够保持

X = a
Y = [b,c,d]

并且该陈述为真。

|除了在头和尾巴上分开之外还做什么?

1 个答案:

答案 0 :(得分:2)

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 | [] ] ]。最后一部分不匹配,因此返回falseXY因此不是问题。问题在于[]是一个常数,它与表示[ 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只是对列表执行统一,就像对其他函子和常量一样。