prolog - 用 `last/2` 或 `append/3` 实现 `reverse/2`

标签 prolog

为什么 SWI-Prolog 文档建议将 append(_, [Last], List) 作为可移植的 last/2 而不是说 reverse(List ,[最后|_])(参见here)? reverse/2 本身是否没有像 append/3 那样广泛实现?还是图片中还遗漏了其他内容?

无论哪种方式,如果列表是循环的,这三个都不会终止:

?- L = [z|L], last(L, Last).
^CAction (h for help) ? abort
% Execution Aborted
?- L = [z|L], append(_, [Last], L).
^CAction (h for help) ? abort
% Execution Aborted
?- L = [z|L], reverse(L, [Last|_]).
^CAction (h for help) ? abort
% Execution Aborted

但是,reverse/2至少不会在正确的列表上留下选择点:

?- append(_, [Last], [a]).
Last = a ;
false.

?- reverse([a], [Last|_]).
Last = a.

最佳答案

reverse/2 的定义实际上不太常见,而且 SWI 的实现具有更好的终止行为,而许多其他实现仅在第一个参数是列表时才终止。我看到至少有 3 种不同的实现:一方面是 SWI,另一方面是 SICStus 和许多其他实现,然后是介于两者中间的 XSB。您可以通过以下目标来区分它们:

reverse(Xs, [a]).     % terminates for SWI and XSB
reverse([a|Xs], [a]). % terminates for SWI

就性能而言,我希望传统的 reverse/2(不是 SWI 的实现)应该更快一点,因为它的运行完全是确定性的。另一方面,它在堆上重新创建整个列表。

在当前的实现中,append(_, [L], Xs) 的实现并不理想:对于列表 Xs 的每个元素,都会创建一个选择点并然后删除,使最后一个选择点保持事件状态。 更多请参见this question .

关于prolog - 用 `last/2` 或 `append/3` 实现 `reverse/2`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28964538/

相关文章:

prolog - 为什么这个查询没有终止?

list - 使用 Prolog 读取记录列表并执行有关先前记录的持续计算

prolog - 具有相同开始和结束的所有子串

list - 为什么我的 Prolog 练习没有尝试其他解决方案?

prolog - 接受2种不同的颜色,但不接受相同的颜色

prolog - prolog '--' 构造的行为?

prolog - Prolog终止域:我如何知道哪些问题将返回有限数量的答案?

prolog - 我应该通过抛出实例化错误来强制模式声明吗?

prolog - 由 swi-prolog 编译的可以接受参数的 .exe 示例

prolog - 列出给定库模块中的谓词