【发布时间】:2013-05-15 16:49:49
【问题描述】:
我在使用 Logtalk 时玩得很开心,但在使用 phrase_from_file 时遇到了问题。具体来说,我的情况是这样的:
:- 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.
问题在于对phrase_from_file 的调用。找不到scanlist,大概是因为它是这个对象的本地,所以我得到这个错误:
?- scan_parser::scan_file('input.txt', Scans).
ERROR: phrase/3: Undefined procedure: pio:scanlist/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: (::)/3
如果我使用pio:phrase_from_file(this::scanlist(Scans), Filename) 或pio:phrase_from_file(scan_parser::scanlist(Scans), Filename) 也是一样。如果我在模拟 SWI 的模块设施时使用单个冒号,我会收到类似 ERROR: phrase/3: Undefined procedure: scan_parser:scanlist/3 的消息。
我认为这里的问题是 SWI 的 PIO 库正在尝试构建一些东西来交给phrase,它只是不够智能。但这是我经常想到的事情,使用phrase_from_file/2,我敢肯定还有其他时候我想从 SWI 的图书馆中挖掘一些东西并借用它。正确的前进方向是什么?我想尽可能保留 Logtalk 的封装性。
谢谢!
【问题讨论】:
-
你好丹尼尔。您使用的是哪个 Logtalk 版本?
-
我使用的是 2.44.1,但如果您认为那里可能没有问题,我会尝试使用 3.0。您可能还需要在错误变得明显之前创建“input.txt”。
-
我强烈建议您迁移到 Logtalk 3.x。但是您偶然发现了 Logtalk 限制(与您使用的版本无关):不支持采用闭包的模块元谓词(请参阅用户手册中的 Prolog 迁移部分)。不过,让我考虑一下替代解决方案。
-
3.0 HEAD 下的行为相同。
-
问题的根源在于 Logtalk 通过(在其他转换中)在末尾添加单个参数(用于传递执行上下文)来编译对象谓词。这与使用采用闭包的模块元谓词冲突,因为模块将(通常通过直接或间接调用 call/N)附加附加参数以从闭包到目标,并且隐藏的执行上下文参数将被捕获中间(Prolog 模块系统不支持 Logtalk)。