Доступ к библиотекам SWI-Prolog из Logtalk
Я получаю много удовольствия от использования 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
,
Я предполагаю, что проблема здесь в том, что библиотека PIO SWI пытается создать что-то, чтобы передать phrase
и это просто недостаточно разумно. Но это то, что подходит мне много, используя phrase_from_file/2
и я уверен, что в другой раз я захочу что-то выкопать из библиотеки SWI и позаимствовать. Какой правильный путь вперед? Я хотел бы максимально сохранить инкапсуляцию Logtalk.
Спасибо!
1 ответ
Я разрабатываю общее решение для 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.
Я не могу проверить, так как вы разместили только часть объектного кода.