通过 Prolog 中的列表递归
Recursion through a list in 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,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
的子句的任何头部统一谓词,因此无法证明。因此,您的谓词定义没有任何问题。只是对列表表示的误解。
我正在尝试在 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,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
的子句的任何头部统一谓词,因此无法证明。因此,您的谓词定义没有任何问题。只是对列表表示的误解。