覆盖 Prolog 中的预定义谓词

Posted

技术标签:

【中文标题】覆盖 Prolog 中的预定义谓词【英文标题】:Override predefined predicate in Prolog 【发布时间】:2014-02-20 16:21:22 【问题描述】:

我写了以下谓词 append/3 来实现两个列表的组合:

append([L|Ls],R,[L|Result]):-append(Ls,R,Result).
append([],X,X).

它给出了正确的输出,但是当我跟踪代码的执行流程时,我得到的是:

1 ?- edit.
true.

2 ?- make.
% //dougal/cs0u$/cyw03u/desktop/lab3 compiled 0.00 sec, 3 clauses
true.

3 ?- trace.
true.

[trace] 3 ?- append([a,b,c],[d,e],X).
   Call: (6) append([a, b, c], [d, e], _G554) ? creep
   Call: (7) lists:append([b, c], [d, e], _G636) ? creep
   Exit: (7) lists:append([b, c], [d, e], [b, c, d, e]) ? creep
   Exit: (6) append([a, b, c], [d, e], [a, b, c, d, e]) ? creep
X = [a, b, c, d, e].

似乎Prolog在第一轮使用了我自己的附加谓词,但是当它进入第二级递归时,Prolog已经使用了库中定义的自己的谓词。

我怎样才能覆盖 Prolog 的预定义谓词(除了给我自己的谓词取另一个名字)?

【问题讨论】:

当我尝试你的例子时(在 SWI Prolog 中),我没有得到相同的结果;它使用了私有append 版本。您使用的是哪个 prolog 解释器? 我也在用 SWI Prolog(版本是 6.2.6) 我使用的是 6.0.2 版本。不确定这是否是结果不同的原因。您是否有更大的上下文,或者您是否看到这些结果只是输入swipl 并将您的代码输入为[user] 对不起,我不能完全理解你的最后一句话,因为我对 Prolog 还是很陌生...... :( 但我写的只是一个简单的快速排序程序,我通常只是双击我的文件 quicksort.pl,在弹出的窗口中输入make.,然后输入[quicksort]. 我的建议是,像我一样重现问题,(1) 输入swipl 命令,获得prolog 提示,(2) 输入[user].,然后按 Enter,(3)只需输入您的 append 代码。然后在 prolog 提示符处,开始跟踪(输入 trace.)和您的示例查询,看看是否得到相同的结果。 【参考方案1】:

append/3 谓词不是 SWI-Prolog 中的内置谓词,而是在模块 lists 中定义的库谓词。执行代码时,此模块可能会自动加载。这里有两个标志可以提供帮助。 autoload 标志控制库的自动加载。可以关闭呼叫set_prolog_flag(autoload, false)。还有另一个标志verbose_autoload,您可以将其设置为true,以便自动加载变得冗长。最后但同样重要的是,您可以使用listing/1 谓词来检查您的代码。试试listing(append/3)。它应该在谓词的子句主体中显示对 list:append/3 的调用。

这是我得到的:

?- set_prolog_flag(verbose_autoload, true).
true.

?- [user].
append([L|Ls],R,[L|Result]):-append(Ls,R,Result).
|: append([],X,X).
|: % user://1 compiled 0.00 sec, 3 clauses
true.

?- listing(append/3).
% autoloading user:listing/1 from /Users/pmoura/lib/swipl-7.1.8/library/listing
% autoloading system:append/3 from /Users/pmoura/lib/swipl-7.1.8/library/lists
lists:append([], A, A).
lists:append([A|B], C, [A|D]) :-
    append(B, C, D).

system:append([], A, A).
system:append([A|B], C, [A|D]) :-
    append(B, C, D).

append([A|B], C, [A|D]) :-
    append(B, C, D).
append([], A, A).

true.

?- trace.
true.

[trace]  ?- append([a,b,c],[d,e],X).
   Call: (6) append([a, b, c], [d, e], _G354) ? creep
   Call: (7) append([b, c], [d, e], _G436) ? creep
   Call: (8) append([c], [d, e], _G439) ? creep
   Call: (9) append([], [d, e], _G442) ? creep
   Exit: (9) append([], [d, e], [d, e]) ? creep
   Exit: (8) append([c], [d, e], [c, d, e]) ? creep
   Exit: (7) append([b, c], [d, e], [b, c, d, e]) ? creep
   Exit: (6) append([a, b, c], [d, e], [a, b, c, d, e]) ? creep
X = [a, b, c, d, e].

[trace]  ?- 

您能否编辑您的帖子并告诉我们导致您获得结果的确切调用顺序?

【讨论】:

我已经用我的通话顺序编辑了帖子。顺便说一句,当我明确键入命令 set_prolog_flag(autoload, false). 时,自动加载不会再次发生。 我无法重现您的结果。我确实注意到您的 lab3 文件似乎包含 10 个子句,但您只向我们展示了 append/3 子句。也许该文件中的其他内容导致了您得到的结果? 我刚刚尝试删除其他代码,只留下 3 行,但我仍然得到相同的结果(编辑后)。但是,如果我使用 [user] 方法,即使我没有明确调用 set_prolog_flag(autoload, false).,我也不会遇到这个问题 如何启动 SWI-Prolog 以便调用 edit/0 知道要编辑哪个文件?如果在调用make 之前和之后调用listing(append/3),你会得到什么?

以上是关于覆盖 Prolog 中的预定义谓词的主要内容,如果未能解决你的问题,请参考以下文章

Prolog 中的子列表谓词

Prolog 中的谓词控制

如何阅读prolog中的谓词

Prolog:如何删除谓词中的对称值

Prolog 中如何表示谓词逻辑?

如何将用户输入转换为 gnu prolog 中的可重用谓词?