Prolog if-then-else构造:-> vs *-> vs. if_ / 3

时间:2018-10-31 16:30:06

标签: if-statement prolog control-structure logical-purity implication

正如我似乎再也找不到的另一个StackOverflow答案中指出的那样,这种模式在实用的Prolog代码中经常出现:

pred(X) :-
    guard(X),
    ...
pred(X) :-
    \+ guard(X),
    ...

许多人试图将其浓缩为

pred(X) :-
    (guard(X) ->
    ...
    ;
    ...).

但是,众所周知,箭头结构破坏了选择点,而且不合逻辑。

在Ulrich Neumerkel和Stefan Kral的"this construct is rarely used,"中,提出了一个名为if_/3的谓词,该谓词是单调且合乎逻辑的,但是在论文中,他们提到了另一个引起我注意的结构:*->

*->构造函数的功能完全类似于上面的未使用过的guard子句示例,因此,由于我不想拥有if_/3和我所要求的条件化条件,因此它似乎非常适合我的使用不太在乎额外的选择点。如果我没记错的话(编辑:我是),它提供与if_/3相同的语义,但不需要在条件谓词上添加“验证”。

但是在SWI文档中,它声称{{3}}对我来说似乎很奇怪。在您尝试进行纯逻辑编程时,*->在我看来似乎比->更好。有什么理由要避免这种结构,还是有一个更好的替代方案来代替整个保护子句/否定的保护子句模式?

2 个答案:

答案 0 :(得分:4)

让我们尝试一下!您提供的模式是:

pred(X) :-
    (    guard(X) ->
         ...
    ;    ...
    ).

我现在使用(*->)/2并按如下所示填写“ ...”:

pred(X) :-
        (   guard(X) *->
            false
        ;   true
        ).

进一步,我以guard/1的形式定义了明显的 pure 谓词:

guard(a).

现在,让我们问pred/1最普遍的查询:有没有解决办法?

?- pred(X).
false.

因此,根据谓词,没有X这样的名词pred(X)

但这是错误,因为实际上有这样的术语:

?- pred(b).
true.

实际上,pred/1有无限多个解决方案。在这种情况下,谓词状态根本不存在是可以接受的吗?当然,因为答案是极其有效地计算的,不是吗?

我们得出结论,(*->)/2具有(->)/2的一个重要缺点:如果不同,它可能会错误地提交给其中一个分支。如果仅进一步实例化条件中出现的变量,则分支将适用。以此方式依赖其参数的 instantiation 的谓词永远不可能是纯净的,因为它抵消了我们期望适用于纯逻辑程序的单调推理。特别是,从逻辑上讲,由于pred(b)成立,我们希望pred(X)(对pred(b)概括)必须不能失败< / em>。一旦此属性中断,您将无法再使用声明性调试和其他重要方法来让您更轻松地理解,推理和管理Prolog程序,而这首先构成了声明式编程的主要吸引力。

您提到的问题可能是What uses does if_3/ have?

答案 1 :(得分:1)

通常命名为 soft-cut 的控制结构可在多个Prolog系统中使用。 CxProlog,ECLiPSe,JIProlog,SWI-Prolog和YAP将其作为*->/2谓词和中缀运算符提供。 Ciao Prolog,SICStus Prolog和YAP提供了具有相同语义的if/3谓词。

这种 soft-cut 控制结构的主要用途是在Logtalk中实现 coinduction ,它在其中起着至关重要的作用。在这种情况之外,我很少使用它。

另一方面,->/2被广泛使用。在 if 部分中的隐式剪切是该构造的局部变量,并且避免使用它,例如在您的示例中,尝试两次尝试证明防护,这可能在计算上很昂贵。它可能不是,但是和剪切一样,只要您充分了解它的优缺点,它就是有用的控制结构。

P.S。 Logtalk为此https://github.com/LogtalkDotOrg/logtalk3/tree/master/tests/prolog/control/soft_cut_2_3*->/2变体和https://github.com/LogtalkDotOrg/logtalk3/tree/master/tests/prolog/control/if_3if/3变体提供了针对此控制结构的单元测试。