为什么这两个序言句子的输出不同?

时间:2018-12-01 18:36:56

标签: prolog

我最近开始学习Prolog,有些事情我不理解。

这两个句子为什么给出不同的输出?
我了解[[| ]表达式必须位于列表的开头,而右侧则位于列表的末尾。
我怀疑这一定是微不足道的,但最后我不明白为什么,因为在第一种情况下,第二种并没有将两个部分统一为一个列表。

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

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

1 个答案:

答案 0 :(得分:2)

第二个不是列表,或者至少不是“ Prolog社区”认为的列表。

如果我们看一下您写的内容,第一个表达式可以看成类似于:

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

这是一个列表:您基本上构造了一个“ cons”,头为 head 2,尾部为另一个列表。请注意,列表的开头是元素,而列表的末尾是包含其余元素的列表。

在第二个示例中,您可能打了错字,也许您写过:

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

在这种情况下,“列表”如下所示:

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

请注意,这实际上不是一个列表:缺点的头部是一个元素,并且这样的元素当然可以是一个列表(因为我们可以构造列表的列表等),但是这里的尾部是只是一个元素。

这意味着人们不能不能使用语法糖,因此用[1,2]之类的语法糖代替。请注意,[1]实际上是[1|[]]的语法糖,而[2,1][2|[1|[]]]的语法糖(如第一幅图所示)。但是[[1]|2]没有这样的语法糖当量。

大多数Prolog解释器允许您以规范的方式编写列表,例如在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

因此,我们认为“ cons”函数是点'.',它是一个函子。)