我正在尝试撤销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如何处理这些列表,以及为什么这两种表示列表的方式不可互换?你能解释一下如何使这段代码有效吗?
谢谢!
答案 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}}谓词的子句的任何头部统一因此无法证明。因此,谓词定义没有任何问题。只是对列表表示的误解。