考虑以下 Prolog 程序。
a(X) :- b(_), c(X).
b(1).
b(2).
b(3).
c(1).
运行查询:
a(X).
在 SWI-Prolog 中,我们得到三个结果,所有 X = 1。
鉴于我们不关心匿名变量,是什么阻止了 SWI-Prolog 返回单个结果?为什么不执行此优化?
谢谢
考虑以下 Prolog 程序。
a(X) :- b(_), c(X).
b(1).
b(2).
b(3).
c(1).
运行查询:
a(X).
在 SWI-Prolog 中,我们得到三个结果,所有 X = 1。
鉴于我们不关心匿名变量,是什么阻止了 SWI-Prolog 返回单个结果?为什么不执行此优化?
谢谢
对于 Prolog 来说,下划线只是一个匿名变量。所以a/1
谓词等价于:
a(X) :-
b(Y),
c(X).
现在回溯该b(Y)
子句可能看起来毫无用处,因为一旦满足,Y
就无处使用,因此不应该对程序的其余部分产生影响。再者Y
没有影响X
所以b(Y)
不应该有半点影响X
。
然而,在真正的 Prolog 中,有些事情可能会产生影响:
b/1
谓词可能会执行I/O。假设谓词实现为:
b(a) :-
print(a).
b(a) :-
print(b).
然后它将a
在第一个分支和b
第二个分支中打印。
b/1
可能会在第二个、第三个、... 路径中引发异常。在这种情况下,我们可能想要处理错误;
b/1
可能会使用asserta/1
,assertz/1
等并更改程序。例如,它可能会添加事实,c/1
以便在第二次运行c/1
中有其他结果。
许多 Prolog 解释器都有一个不可回溯的存储,这样不同的回溯路径可以相互共享信息。
其他编码设施,例如 的结果b/1
可能对c/1
.
您可以通过使用元谓词来避免这种回溯。例如:b/1
once/1
a(X) :-
once(b(_)),
c(X).