这是第一个观察结果:
?- is_list([]), is_list([_,_,_]).
true.
这是另一个观察结果:
?- [] = _, [_,_,_] = _.
true.
因此,为什么要is_list/1
实施
?- is_list(_).
false.
或
?- is_list([_|_]).
false.
_
可以清楚地与列表统一吗?这不是逻辑上更健全的true
吗?
在SWI-Prolog's documentation for is_list/1
中,有一条说明:
在5.0.1之前的版本中,
is_list/1
刚刚检查过[]
或[_|_]
,proper_list/1
具有当前is_list/1
的角色。目前的定义符合事实上的标准。
为什么这是事实上的标准?
答案 0 :(得分:6)
正如您所看到的那样,is_list/1
不健全,或者说不完整,因为错误表示有当提出最常见的查询时,无论如何。
?- is_list(Ls). false.
没有列表?加油!
所有遗传类型检查谓词如atom/1
,integer/1
等共享这个不幸的特征,当这些谓词在标记正确反对其建议的人之后被构思出来时,其不正确性已经很明显语义学是“纯粹主义者”(当时,这个词已经缺少了这个词后来获得的互补性)。
案例如:
?- is_list(Ls), Ls = []. false. ?- Ls = [], is_list(Ls). Ls = [].
清楚地表明,从逻辑的角度来看,某些事情从根本上被打破了这种非单调测试。 “Prolog的(,)/2
不是逻辑联合”,是的,如果您在代码中首先使用不合逻辑的谓词。否则,(,)/2
始终是目标的逻辑结合。
一个干净且逻辑上正确的方法是在无法确定的情况下抛出实例化错误。
library(error)
,特别是 must_be/2
,在继承的不合逻辑谓词的不正确性变得无法忍受后,即使对于Prolog的临时用户来说,也会进入健全的方向:
?- must_be(list, X). Arguments are not sufficiently instantiated ?- must_be(list, [_|_]). Arguments are not sufficiently instantiated ?- must_be(list, [a,b,c]). true.
must_be/2
易于使用,是迈向更正确的逻辑程序的良好的第一步。其他结构也出现在地平线上,我希望其他人对现状进行评论。
现在对于实际的措辞:抛开上面概述的基本问题,SWI文档中提到的争论是检查最外面的函子是否足够将术语视为列表,或者是否该列表必须实际符合列表的归纳定义,即:
[]
是一个列表。Ls
是列表,则'.'(_, Ls)
是列表。请注意,在最近的SWI版本中,[]
甚至不是原子,所以它再次打破这个概念。