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
就不会被使用,因此不应该对程序的其余部分产生影响。此外 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) :-
<b>once(</b>b(_)<b>)</b>,
c(X).
考虑以下 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
就不会被使用,因此不应该对程序的其余部分产生影响。此外 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) :-
<b>once(</b>b(_)<b>)</b>,
c(X).