如果另一个谓词失败,则调用谓词 [英] Call a predicate if another predicate failed
问题描述
如果对另一个谓词的所有调用都失败了,我如何调用一个谓词?
How can I call a predicate if all calls to another predicate failed?
我有:
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
最终会被执行.
- at any time, If
bar1/2
has succeded,bar2/3
will never be executed. - if all
bar1/2
calls failed, thenbar2/3
will eventually be executed.
样本回溯树
root root
|
/ \ |
/ \ all bar1 failed |
/ \ |
/ | \ \ ===>>>======>>>> |
/ | \ \ |
F F F F E
time 0 1 2 3 4
Abbreviation:
Bar1 failed : F
Bar2 executed : E
推荐答案
您正在寻找所谓的软剪辑",
You're looking for what's known as "soft cut",
A *-> B ; C.
这相当于 (A,B) ;(\+A,C)
:如果A
至少成功一次,上面等价于A,B
.如果不是,它就相当于 C
.目标 A
不会重试.
This is equivalent to (A,B) ; (\+A,C)
: if A
succeeds at least once, the above is equivalent to A,B
. If not, it's equivalent to just C
. The goal A
is not retried.
简单的 if
构造允许测试谓词只成功一次:
Simple if
construct allows the test predicate to succeed only once:
A -> B ; C.
等价于 (几乎 - 详情请参见手册) 到 (once(A),B) ;(\+A,C)
,除了不重试目标 A
.
is equivalent (almost - see you manual for details) to (once(A),B) ; (\+A,C)
, except that the goal A
isn't retried.
你的情况应该是
foo(A, B, C, D) :-
(bar1(Y,Z) *-> true ; bar2(L, K, M)),
foo(A, B, C, D).
补充:一些 Prolog 实现可能没有这个结构 *->
可用(例如 gprolog).在那种情况下,我看到了两种可能性.要么
addition: Some Prolog implementations might not have this construct *->
available (e.g. gprolog). In that case I see two possibilities. Either
(A , B) ; (\+A , C)
虽然它会重试A
,或者(为A编写goal(X)
)
although it would retry A
, or (writing goal(X)
for A)
bagof(g(X), goal(X), L) -> ( member(g(X), L), B ) ; C
当然,副作用的顺序会因此而改变.应该选择变量的名称L
,这样它在B
中不会出现自由.
Of course the order of side-effects will be changed by this. The name L
of the variable should be chosen such that it does not appear free in B
.
这篇关于如果另一个谓词失败,则调用谓词的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!