if-statement - Prolog if-then-else 结构:-> vs *-> vs. if_/3
问题描述
正如我似乎再也找不到的另一个 StackOverflow 答案中所述,这种模式经常出现在实际的 Prolog 代码中:
pred(X) :-
guard(X),
...
pred(X) :-
\+ guard(X),
...
许多人试图将其浓缩为
pred(X) :-
(guard(X) ->
...
;
...).
然而众所周知,箭头结构破坏了选择点并且不合逻辑。
在 Ulrich Neumerkel 和 Stefan Kral 的Indexing dif/2中,提出了一个单调且合乎逻辑的谓词if_/3
,但是在论文中他们提到了另一个引起我注意的构造:*->
.
该*->
构造函数的功能与上面的未加糖保护子句示例完全相同,因此它似乎非常适合我的使用,因为我不想拥有所需的具体条件,if_/3
而且我不太关心额外的选择点。如果我没记错的话(编辑:我是),它提供了与条件谓词相同的语义,if_/3
但不需要将“具体化”添加到条件谓词中。
然而,在它的 SWI 文档中,它声称“这种结构很少使用”,这对我来说似乎很奇怪。在我看来,这比您尝试进行纯逻辑编程时要*->
好得多。->
是否有任何理由避免这种结构,或者是否有更好的替代整个保护条款/否定保护条款模式?
解决方案
让我们试试吧!你给的模式是:
预测(X):- (守卫(X)-> ... ; ... )。
我现在使用(*->)/2
并填写“...”如下:
预测(X):- (守卫(X)*-> 假 ; 真 )。
此外,作为guard/1
,我定义了明显的纯谓词:
后卫(一)。
现在,让我们问pred/1
一个最普遍的问题:有什么解决方案吗?
?- pred(X)。 错误的。
所以,根据谓词,没有X
这样的词pred(X)
是真的。
但这是错误的,因为实际上有这样一个术语:
?- pred(b)。 真的。
事实上,pred/1
有无穷多的解。在这种情况下,谓词状态根本没有是可以接受的吗?当然,因为答案的计算效率非常高,不是吗?
我们得出的结论是,它(*->)/2
有一个重要的缺点:如果仅进一步实例化条件中出现的变量,则在适用不同(->)/2
分支的情况下,它可能会错误地提交到其中一个分支。以这种方式依赖于其参数的实例化的谓词永远不可能是纯的,因为它抵消了我们期望适用于纯逻辑程序的单调推理。特别是,从逻辑的角度来看,既然成立,我们期望是 的概括,一定不能失败pred(b)
pred(X)
pred(b)
. 一旦这个属性被破坏,你就不能再应用声明式调试和其他让你更容易理解、推理和管理 Prolog 程序的重要方法,而这首先构成了声明式编程的主要吸引力。
您提到的问题可能是What uses does if_3/
have ? .