Prolog 中的谓词控制 [英] Predicate control in Prolog

查看:13
本文介绍了Prolog 中的谓词控制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对 Prolog 谓词控制有兴趣.

Have a curiosity related to Prolog predicate control.

假设我有一个谓词 f(A,X) 和 g(B).

Supposedly I have a predicate f(A,X) and g(B).

f(A,X):- a,b,c, g(X).
g(B):- true.

a - returns true
b - returns true.
c - returns false.
where a,b and c are random predicates.

如果 c 返回 false,我如何继续评估谓词 f(A,X) 中的 g(X)?

How can I continue to evaluate g(X) in the predicate f(A,X) if c returns false?

推荐答案

如果你的意图是定义 f(A,X) 使得 g(X) 应该评估 c 是否失败,然后:

If your intention is to define f(A,X) such that g(X) should be evaluated whether or not c fails, then either:

  1. 您可以使用蕴含 (->) 和/或析取 (;)、
  2. f(A,X) 不需要用 c来定义.这假设 c 没有副作用(例如,使用 assert 断言数据库事实,或将 IO 打印到流中)会改变环境和c 失败时无法撤消,在这种情况下首选第一个选项.
  1. You could encode this using implication (->) and/or disjunction (;), or
  2. f(A,X) doesn't need to be defined in terms of c. This assumes c has no side-effects (e.g., asserting database facts using assert, or printing IO to a stream) which alter the environment and which cannot be undone on failure of c, in which case the first option is preferable.

使用析取有几种替代方法,例如:

There are several alternatives for using disjunction, such as:

f(A,X) :- ((a, b, c) ; (a, b)), g(X).

这个定义(上图)根本不依赖于c,但它总是会执行c(只要ab 成功).如果 c 完全失败,则析取 (;) 允许 PROLOG 回溯以尝试执行 a, b again,并继续到 g(X).请注意,这相当于:

This definition (above) doesn't depend on c at all, but it will always execute c (as long as a and b succeed). The disjunction (;) allows PROLOG to backtrack to try executing a, b again if c failed at all, and to continue onto g(X). Note that this is equivalent to:

f(A,X) :- a, b, c, g(X).
f(A,X) :- a, b, g(X).

为了让 PROLOG 不回溯两次评估 f(A,X) 因为第二个(相同的)头谓词 f(A,X) 对于每个评估,您可以选择放置一个剪切 (!),如果您的实现支持它,紧跟第一个子句中的 c 子目标之后.剪切被放置在 c 之后,因为我们不希望解释器提交 f(A,X) 子句的选择 if c 失败了,相反,我们希望解释器在这个子句中失败并尝试下一个子句,有效地忽略 c 并继续处理 g(X).

In order for PROLOG not to backtrack to evaluate f(A,X) twice because of the second (identical) head predicate f(A,X) for every evaluation, you may choose to place a cut (!), if your implementation supports it, immediately after the c subgoal in the first clause. The cut is placed after c because we don't want the interpreter to commit to that choice of f(A,X) clause if c had failed, instead, we want the interpreter to fail out of this clause and to try the next one, to effectively ignore c and to continue processing g(X).

还要注意,这个解决方案依赖于没有副作用的 ab,因为当 c 失败时,ab 再次执行.如果所有abc都有副作用,可以尝试使用implication:

Also note that this solution relies on a and b having no side-effects, because when c fails, a and b are executed again. If all a, b, and c have side effects, you can try using implication:

f(A,X) :- a, b, (c -> g(X) ; g(X)).

无论 c 是否失败,这也将始终有效地执行 g(X),并且不会执行 ab如果 c 失败,则再次 .这个单子句定义也不会像前面的建议那样留下选择点.

This will also effectively always execute g(X) whether c fails or not, and will not execute a and b again if c fails. This single-clause definition will also not leave a choice-point like the previous suggestion.

这篇关于Prolog 中的谓词控制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆