为什么在性能方面,复合术语优于列表?例如,
matrix(row(1,2,3),row(1,2,3),row(1,2,3))
更好的选择是
[[1,2,3],[1,2,3],[1,2,3],[1,2,3]]
matrix(row(1,2,3),row(1,2,3),row(1,2,3))
更好的选择是
[[1,2,3],[1,2,3],[1,2,3],[1,2,3]]
首先,明确一点:列表是一种复合术语。
要了解列表是什么,请使用write_canonical/1
。例如,在使用GNU Prolog时:
| ?- write_canonical([1,2,3]).
'.'(1,'.'(2,'.'(3,[])))
row(1,2,3)
,需要以下内容:
.(1, .(2, .(3, [])
,在简单直观的内存表示中,您需要:
'.'/2
functors[]
)。另一个(优秀的)答案没有提到的一点:
通过位置访问列表成员意味着您需要遍历列表。访问术语的参数应该在常数时间内可行。因此,对于随机访问,术语应更有效率。
简短的旁白:您可以尝试使列表遍历稍微快一些。但是,SWI-Prolog实现的nth0_det/3
几乎让人绝望;)
您可能会对此主题感兴趣,特别是这个摘要,其中涉及列表和术语等内容。
以下是一些经验法则。
用例:
效率:
从最后一点可以得出结论:尝试找到使用链接列表而不是随机访问数组的算法。这并不总是可能的,但对于许多问题,您有选择。经典示例将是快速排序与归并排序:在Prolog中,归并排序肯定更快。
无论哪种方式,首先确保正确理解问题,然后再考虑效率。并确保在开始优化之前测量性能瓶颈。
选择最佳算法和数据结构当然意味着您需要了解自己的问题和可用工具。虽然与您的问题无关,但C ++的“标准模板库”的美妙之处在于,对于算法和数据结构,时间复杂度(“大O表示法”)是固有属性,而不是实现细节。
sort/4
谓词,我找不到玩转纯Prolog排序的好借口。 - user1812457functor(arg1, arg2, ..., argn, ...)
的复合术语,我们可以使用标准的arg/3
内置谓词以便对任何参数实现常量访问。即对于任何明智的Prolog实现,O(N)与O(1)相比。arg/3
的解决方法更快。但这也将取决于所使用的Prolog系统。如果性能是主要关注点,则基准测试非常重要。只需避免在微观层面上进行测试,而应考虑如何在处理相关应用程序的所有部分中创建和访问术语。
[]
和术语'.'/2
,因此(浅层)第一个参数索引无法区分长度为1、2、3等的列表。支持列表:您的Prolog系统可能对复合术语的元数*有继承限制,因此在某些情况下,使用类似列表的结构可能需要表示大量元素的集合。Richard的书包含更多有关这两个方面以及其他方面的宝贵信息。 - mat