Prolog:冗余导致涉及匿名变量的子句

Prolog: Redundant results in clauses involving anonymous variables

考虑以下 Prolog 程序。

a(X) :- b(_), c(X).

b(1).
b(2).
b(3).

c(1).

运行查询:

a(X).

在 SWI-Prolog 中,我们得到三个结果,所有 X = 1。

鉴于我们不关心匿名变量,是什么阻止了 SWI-Prolog return 单个结果?为什么不执行此优化?

谢谢

好吧,对于 Prolog,下划线只是一个 匿名变量 。所以 a/1 谓词等同于:

a(X) :-
    b(<b>Y</b>),
    c(X).

现在回溯 b(Y) 子句可能看起来毫无用处,因为一旦它得到满足,Y 就不会被使用,因此不应该对程序的其余部分产生影响。此外 YX 没有影响,因此 b(Y) 不应该对 X.

有丝毫影响

但是在真正的 Prolog 中,有些事情可能会产生影响:

  1. b/1 谓词可能执行I/O。假设谓词实现为:

    b(a) :-
        print(a).
    b(a) :-
        print(b).
    

    然后它将在第一个分支中打印 a,在第二个分支中打印 b

  2. b/1 可能 在第二个、第三个……路径中引发异常。在这种情况下,我们可能想要处理错误;

  3. b/1 可能会使用 asserta/1, assertz/1 等,并且 改变程序 。例如,它可能会为 c/1 添加事实,以便在第二个 运行 c/1 中有其他结果。

  4. 很多 Prolog 解释器都有一个 non-backtrackable store 这样不同的回溯路径可以相互共享信息。

  5. 其他编码工具,例如 b/1 的结果可能会影响 c/1

您可以使用 once/1 元谓词 避免 超过 b/1 的回溯。例如:

a(X) :-
    <b>once(</b>b(_)<b>)</b>,
    c(X).