且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

跨模块的“接口"调用 SWI-Prolog

更新时间:2022-06-27 01:06:11

一个有趣的问题.遵循完全可移植的 Logtalk 解决方案(对可移植性进行了微小的更改,并避免了对讨厌的 double_quotes 标志的依赖;format/2 是事实上的标准谓词,它接受第一个参数,但谓词可用的方式取决于 Prolog 系统,并且不需要用这些细节来混淆代码):

An interesting problem. Follows a fully portable Logtalk solution (with minor changes for portability and avoiding dependencies on the pesky double_quotes flag; format/2 is a de facto standard predicate that accepts an atom in the first argument but the way the predicate is made available depends on the Prolog system and there's no need of cluttering the code with those details):

:- protocol(toolshed).

    :- public(toolshed/1).

:- end_protocol.


:- category(helper).

    :- private(helper/2).

    helper(friar_tuck, help) :-
        write('I will help you rout the Sheriff of Nottingham\'s men!\n'),
        setof(X, ::toolshed(X), Tools),
        write('I found these tools: '), writeq(Tools), nl,
        write('Have at them!\n').

    helper(merlin, help) :-
        write('I will help you rout Mordred\'s army!\n'),
        setof(X, ::toolshed(X), Tools),
        write('I found these tools: '), writeq(Tools), nl,
        write('Have at them!\n').

:- end_category.


:- object(robin,
    implements(toolshed),
    imports(helper)).

    :- public(robin_hood/0).

    robin_hood :-
        ^^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').

:- end_object.


:- object(arthur,
    implements(toolshed),
    imports(helper)).

    :- public(arthur/0).

    arthur :-
        ^^helper(merlin, help).

    toolshed('a slightly musty grimoire').
    toolshed('a jar of mandragore').
    toolshed('a fresh toadstool').

:- end_object.

然后(假设上面的代码保存在一个 dh.lgt 文件中):

Then (assuming the above code saved in a dh.lgt file):

$ swilgt
...

?- {dh}.
...
true.

?- robin::robin_hood.
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!~n
true.

?- arthur::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!~n
true.

您不仅可以使用 Logtalk,还可以使用其所有支持的后端 Prolog 系统运行此解决方案.

You can run this solution not only with Logtalk but with all its supported backend Prolog systems.

如果您不希望 toolshed/1 谓词是公开的,您可以更改对象打开指令,使谓词成为受保护的或私有的.例如:

If you don't want the toolshed/1 predicate to be public, you can change the object opening directives to make the predicate either protected or private. For example:

:- object(robin,
    implements(private::toolshed),
    imports(helper)).

这会给你:

?- arthur::toolshed(T).
!     Permission error: access private_predicate toolshed/1
!       in goal: arthur::toolshed(A)

您也可以更改协议以将谓词设为私有,但这并不符合习惯.

You could also change the protocol to make the predicate private there but that would not be idiomatic.