从Logtalk访问SWI Prolog库

从Logtalk访问SWI Prolog库,prolog,dcg,logtalk,Prolog,Dcg,Logtalk,我在使用Logtalk时玩得很开心,但是在使用文件中的短语时遇到了一个问题。具体来说,我的案例如下: :- object(scan_parser). :- public(scanlist//1). scanlist([Scan|Scans]) --> scan(Scan), dcg_basics:blanks, scanlist(Scans). scanlist([]) --> []. :- public(scan_file/2). :- mode(

我在使用Logtalk时玩得很开心,但是在使用文件中的短语时遇到了一个问题。具体来说,我的案例如下:

:- object(scan_parser).

   :- public(scanlist//1).
   scanlist([Scan|Scans]) --> scan(Scan), dcg_basics:blanks, scanlist(Scans).
   scanlist([]) --> [].

   :- public(scan_file/2).
   :- mode(scan_file(+filename, -scans), one).
   scan_file(Filename, Scans) :- pio:phrase_from_file(scanlist(Scans), Filename).

   ...
:- end_object.
问题在于从_文件调用
短语_。它无法找到
scanlist
,可能是因为它是此对象的本地对象,因此我得到以下错误:

?- scan_parser::scan_file('input.txt', Scans).
ERROR: phrase/3: Undefined procedure: pio:scanlist/3
?- scan_parser::scan_file('input.txt', Scans).
ERROR: phrase/3: Undefined procedure: pio: (::)/3
但是,如果我试图用这样的模块引用来扩展它:

scan_file(Filename, Scans) :- pio:phrase_from_file(::scanlist(Scans), Filename).
我得到这个错误:

?- scan_parser::scan_file('input.txt', Scans).
ERROR: phrase/3: Undefined procedure: pio:scanlist/3
?- scan_parser::scan_file('input.txt', Scans).
ERROR: phrase/3: Undefined procedure: pio: (::)/3
如果我使用来自\u文件的
pio:phrase\u(this::scanlist(Scans),Filename)
或来自\u文件的
pio:phrase\u(scan\u parser::scanlist(Scans,Filename)
。如果我在模拟SWI的模块功能时使用一个冒号,则会收到类似以下消息:错误:短语/3:未定义过程:扫描\u解析器:扫描列表/3

我假设这里的问题是,SWI的PIO库正在尝试构造一些东西来交给
短语
,但它不够智能。但这是我经常想到的事情,使用的是文件/2中的
短语,我确信还有其他时候我想从SWI的图书馆中挖掘一些东西并借来。正确的前进方向是什么?我希望尽可能保留Logtalk的封装


谢谢

我正在为Logtalk 3.x设计一个通用解决方案,以支持将闭包作为元参数的Prolog模块元谓词。同时,您可以尝试以下(丑陋的)解决方法:

% ensure the module is loaded
:- use_module(library(pio)).


:- object(scan_parser).

    % override the non-standard meta-arguments declarations
    :- meta_predicate(pio:phrase_from_file(2,*)).

   :- public(scanlist//1).
   scanlist([Scan|Scans]) --> scan(Scan), dcg_basics:blanks, scanlist(Scans).
   scanlist([]) --> [].

   :- public(scan_file/2).
   :- mode(scan_file(+filename, -scans), one).
   scan_file(Filename, Scans) :- pio:phrase_from_file(user:scan_parser_scanlist(Scans), Filename).

    {scan_parser_scanlist(Scans, A, B)} :-
        phrase(scanlist(Scans), A, B).

    ...

:- end_object.

我无法测试,因为您只发布了部分目标代码。

嗨,Daniel。您使用的是哪个Logtalk版本?我使用的是2.44.1,但如果您认为3.0可能没有问题,我会尝试使用。在错误变得明显之前,您可能还需要创建“input.txt”。我强烈建议您转到Logtalk 3.x。但是您偶然发现了一个Logtalk限制(与您使用的版本无关):不支持使用闭包的模块元谓词(请参阅用户手册上的Prolog迁移部分)。但是,让我考虑一下另一种解决方案。3.0 HEAD下的行为相同。问题的根源在于Logtalk通过(在其他转换中)在末尾添加单个参数(用于传递执行上下文)来编译对象谓词。这与使用模块元谓词的冲突有关:模块关闭(通常直接或间接调用CAL/N)附加的参数从闭包转到目标,隐藏的执行上下文参数将被捕获在中间(Prolog模块系统不知道LogoTalk)。谢谢!如果遇到其他类似情况,我很高兴能找到解决办法。刚刚更新的Logtalk 3.x HEAD应该为(:)/2非终端提供更快的生成代码,就像您发布的代码一样。上述限制(关于调用以闭包作为元参数的Prolog模块元谓词)Logtalk 3.00.0 Alpha 17包含了支持从对象和类别内部调用的更改,包括Prolog内置元谓词和Prolog模块元谓词,它们将闭包作为元参数。您发布的代码应该按原样工作,不需要任何变通方法。