覆盖 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 中的预定义谓词的主要内容,如果未能解决你的问题,请参考以下文章