【发布时间】:2026-01-11 03:15:01
【问题描述】:
这可能特定于 SWI Prolog 模块系统。
假设我们有三个 Prolog 模块(在 SWI-Prolog 模块系统中):
-
robin(在文件robin.pl中) -
arthur(在文件arthur.pl中) -
helper(在文件helper.pl中)。
谓词robin:robin/0(即模块robin中的谓词robin_hood/0)和谓词arthur:arthur/0调用谓词helper:helper/2(由模块helper导出)。
谓词helper:helper/2 然后应该调用谓词toolshed/1,这不同取决于调用者模块。我希望helper/2 调用与调用helper/2 的谓词关联的toolshed/1 谓词。
在 Java 中,可以将带有toolshed() 方法的接口传递给helper(),以便helper() 可以调用该接口并最终得到正确的实现。
我如何在 Prolog 中做到这一点?
示例代码:
robin.pl
:- module(robin,
[
robin/0
,toolshed/1
]).
:- use_module(library('helper.pl')).
robin :- helper(friar_tuck,help).
toolshed('a katana made by mastersmith Masamune').
toolshed('an ancient shovel with a sharpened blade').
toolshed('an Uzi 9mm with Norinco markings').
亚瑟.pl
:- module(arthur,
[
arthur/0
,toolshed/1
]).
:- use_module(library('helper.pl')).
arthur :- helper(merlin,help).
toolshed('a slightly musty grimoire').
toolshed('a jar of mandragore').
toolshed('a fresh toadstool').
helper.pl
:- module(helper,
[
helper/2
]).
helper(friar_tuck,help) :-
format("I will help you rout the Sheriff of Nottingham's men!~n"),
setof(X,toolshed(X),Tools),
format("I found these tools: ~q~n",[Tools]),
format("Have at them!~n").
helper(merlin,help) :-
format("I will help you rout Mordred's army!~n"),
setof(X,toolshed(X),Tools),
format("I found these tools: ~q~n",[Tools]),
format("Have at them!~n").
把他们放到导演testing:
testing
├── arthur.pl
├── helper.pl
└── robin.pl
启动swipl,设置库搜索路径并加载arthur.pl:
?- assertz(file_search_path(library,'/home/me/testing')).
true.
?- use_module(library('arthur.pl')).
true.
?- arthur.
I will help you rout Mordred's army!
I found these tools: ['a fresh toadstool','a jar of mandragore','a slightly musty grimoire']
Have at them!
true.
所以这行得通。 toolshed/1 由模块 arthur 导出,并且由模块 helper 可见(并且可调用 unqalified),即使 helper 不导入 arthur.pl(不太确定它是如何工作的,mabye属于当前在堆栈上的谓词的所有模块的导出谓词是可见的并且可以无条件访问吗?)。
但我也无法加载robin.pl:
?- use_module(library('robin.pl')).
ERROR: import/1: No permission to import robin:toolshed/1 into user (already imported from arthur)
true.
好的,这并不奇怪。但是我怎样才能得到我想要的结果呢?我想看看这个:
?- use_module(library('robin.pl')).
true.
?- robin.
I will help you rout the Sheriff of Nottingham's men!
I found these tools: ['a katana made by mastersmith Masamune','an Uzi 9mm with Norinco markings','an ancient shovel with a sharpened blade']
Have at them!
true.
【问题讨论】:
-
我尝试将
toolshed/1的multifile/1指令放在arthur.pl和robin.pl中,但这会产生同样的问题。 -
您可以使其与多文件谓词一起使用。请参阅我的替代答案。了解所有这些替代方案的优缺点是一个很好的学习练习。
-
你不能将
helper/2变成helper/3并将其传递给在本地toolshed/1中找到的工具列表吗? -
@PaulBrown 当然,在这种情况下您可以“序列化”结果(特别是因为列表不太长),但在一般情况下不会如此。在控制反转方法中,“工具库”是一些回调谓词,只有在将来调用它才有意义。将“helper”想象成事件处理程序,将“toolshed”想象成事件处理代码,将模块想象成可插拔组件。
-
是的,我想知道这是代表更一般的情况还是要解决的实际问题。
标签: module interface prolog swi-prolog