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

时间:2017-09-02 21:48:07

标签: prolog

考虑以下Prolog程序。

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

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

c(1).

运行查询:

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

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

由于

1 个答案:

答案 0 :(得分:4)

对于Prolog来说,下划线只是一个匿名变量。因此a/1谓词相当于:

a(X) :-
    b(Y),
    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/1assertz/1等,并更改程序。例如,它可能会为c/1添加事实,以便在第二轮c/1中有其他结果。

  4. 许多Prolog口译员都有non-backtrackable store这样不同的回溯路径,可以互相分享信息。

  5. 其他编码工具,b/1的结果可能会对c/1产生影响。

  6. 您可以使用once/1元谓词避免此回溯而不是b/1。例如:

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