Доступ к библиотекам 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.

Я не могу проверить, так как вы разместили только часть объектного кода.

Другие вопросы по тегам