如果另一个谓词失败,则调用谓词

时间:2012-06-04 09:08:01

标签: prolog

如果对另一个谓词的所有调用都失败了,我如何调用谓词?

我有:

foo(A, B, C, D) :-
    (bar1(Y,Z); bar2(L, K, M)),
    foo(A, B, C, D).

我想要的是什么:

  • 在任何时候,如果bar1/2成功,bar2/3将永远不会被执行。
  • 如果所有bar1/2次调用失败,则最终将执行bar2/3

示例反馈树

            root                                           root                 
                                                            |
           /   \                                            |
          /     \          all bar1 failed                  |
         /       \                                          |
        / | \     \        ===>>>======>>>>                 |
       /  |  \     \                                        |
      F   F  F     F                                        E
time  0   1  2     3                                        4 

Abbreviation:
       Bar1 failed : F
       Bar2 executed : E

1 个答案:

答案 0 :(得分:1)

你正在寻找所谓的“软切”,

A *-> B ; C.

这相当于(A,B) ; (\+A,C):如果A成功至少一次,则上述内容相当于A,B。如果没有,则相当于C。目标A未重试。

简单if构造允许测试谓词只成功一次:

A -> B ; C.

等同于(几乎 - 请参阅手册了解详情)(once(A),B) ; (\+A,C),但目标A未重试。

因此,您的案件应为

foo(A, B, C, D) :-
    (bar1(Y,Z) *-> true ; bar2(L, K, M)),
    foo(A, B, C, D).

另外: 某些Prolog实现可能没有此构造*->可用(例如gprolog)。在那种情况下,我看到两种可能性。任

(A , B) ; (\+A , C)

虽然它会重试A,或者(写goal(X)代表A)

bagof(g(X), goal(X), L) -> ( member(g(X), L), B ) ; C 

当然,副作用的顺序会因此而改变。应选择变量的名称L,使其在B中不显示为空闲。