考虑以下Prolog程序。
a(X) :- b(_), c(X).
b(1).
b(2).
b(3).
c(1).
运行查询:
a(X).
在SWI-Prolog中,我们得到三个结果,所有X = 1。
鉴于我们不关心匿名变量,是什么阻止SWI-Prolog返回单个结果?为什么没有执行此优化?
由于
答案 0 :(得分:4)
对于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口译员都有non-backtrackable store这样不同的回溯路径,可以互相分享信息。
其他编码工具,b/1
的结果可能会对c/1
产生影响。
您可以使用once/1
元谓词避免此回溯而不是b/1
。例如:
a(X) :-
once(b(_)),
c(X).