通过Prolog中的列表递归

时间:2015-02-21 22:15:56

标签: prolog

我正在尝试撤销Prolog中的列表。我用['item1', 'item2']调用它时效果正常,但用['item1'|'item2']调用它时没有。我和Prolog处于初级阶段,但我认为这两个符号本质上是可以互换的吗?

这是我正在使用的代码:

reverse_list([], Acc, Acc).
reverse_list([Head|Tail], Acc, Reversed) :-
    reverse_list(Tail, [Head|Acc], Reversed). 

reverse_list(List,Reversed) :-
    reverse_list(List,[],Reversed).

问题在于使用列表尾部进行递归调用

当我使用列表['item1', 'item2']调用它时,调试器显示它正常工作,使用尾部作为['item2']进行递归调用,应该如此。

当我用['item1'|'item2']调用它时,调试器显示它尝试使用'item2'进行递归调用,该调用失败,可能是因为它不是列表。

我读到使用[Head|Tail]时Tail将始终是一个列表,但看起来并非如此。

你能解释Prolog如何处理这些列表,以及为什么这两种表示列表的方式不可互换?你能解释一下如何使这段代码有效吗?

谢谢!

1 个答案:

答案 0 :(得分:2)

列表的尾部是一个列表。例如:

| ?- [1,2,3] = [Head| Tail].
Head = 1
Tail = [2,3]
yes

您用作参数['item1'|'item2']的复合词是列表:

| ?- ['item1'|'item2'] = [Head| Tail].
Head = item1
Tail = item2
yes

您需要改为编写[item1|[item2]],这与[item1,item2]完全相同:

| ?- [item1|[item2]] = [item1,item2]. 
yes

由于列表符号是语法糖,您可以使用标准write_canonical/1谓词来检查列表结构:

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

| ?- write_canonical([item1, item2]).
'.'(item1,'.'(item2,[]))
yes

| ?- write_canonical([item1| item2]).
'.'(item1,item2)
yes

调用reverse_list([item1|[item2]], Reversed)时,当您获得reverse_list(item2, ..., ...)时,目标会在第一次递归调用时失败,该reverse_list/3不会与{{1}}谓词的子句的任何头部统一因此无法证明。因此,谓词定义没有任何问题。只是对列表表示的误解。