Как писать / редактировать собственные сопрограммы в Прологе?

Я хотел бы построить свои собственные сопрограммы в Прологе. Я хотел бы добавить некоторые дополнительные функции.

2 ответа

Решение

Одним из возможных решений будет использование механизма расширения терминов, предоставляемого некоторыми системами Prolog и Logtalk, для перезаписи вызовов, например, в freeze/2 Предикат, чтобы сделать дополнительные шаги, которые вы хотите. Однако нужно быть осторожным, чтобы не расширить вызов предиката в другую цель, которая вызывает тот же предикат, что и расширение цели рекурсивно применяется до тех пор, пока не будет достигнута фиксированная точка. Реализация механизма расширения терминов в Logtalk позволяет легко избежать этой ловушки (с дополнительным преимуществом переносимости, поскольку вы можете использовать Logtalk с большинством систем Prolog), используя конструкцию управления обходом компилятора, {}/1, Глупый пример будет:

:- object(my_expansions,
    implements(expanding)).

    goal_expansion(
        freeze(Var,Goal),
        (   write('If you instantiate me, I will run away!\n'),
            {freeze(Var,Goal)},  % goal will not be further expanded
            write('Bye!\n')
        )
    ).

:- end_object.

Этот объект может затем использоваться в качестве объекта ловушки для компиляции исходных файлов, содержащих обращения к freeze/2 что вы хотите расширить. Что-то вроде (при условии, что объект выше сохранен в файле с именем my_expansions.lgt и что исходный файл, который вы хотите расширить, называется source.lgt):

?- logtalk_load(my_expansions), logtalk_load(source, [hook(my_expansions)]).

Для получения полной информации см. Документацию и примеры Logtalk.

Возможно, существует простой способ, чтобы я не знал, что делать то же самое можно с помощью собственной реализации механизма расширения терминов системы Prolog. Кто-нибудь?

Написание ванильного переводчика для сопрограмм должно быть в списке преподавания каждого курса Пролог. Это довольно просто, здесь вы видите обычный ванильный интерпретатор, упрощенный:

% solve(+Term)
solve(true).
solve((A,B)) :- solve(A), solve(B).
solve(H) :- clause(H, B), solve(B).

Теперь для определения соответствия, в смысле приостановки целей с помощью freeze/2, просто добавьте дополнительную пару входных выходных параметров с отложенными целями, для спецификации select/3 см. (*):

% solve(+Term, +List, -List)
solve(G, L, R) :- select(freeze(V, F), L, H), 
   nonvar(V), !, 
   solve((F,G), H, R).
solve(freeze(V, G), L, [freeze(V,G)|L]) :- var(V), !.
solve(freeze(_, G), L, R) :- solve(G, L, R).
solve(true, L, L).
solve((A,B), L, R) :- solve(A, L, H), solve(B, H, R).
solve(H, L, R) :- clause(H, B), solve(B, L, R).

Вы можете использовать вышеупомянутый ванильный переводчик для изучения различных стратегий пробуждения. Я не уверен, захватывает ли он существующие системы Prolog. Но вы можете запустить примеры, такие как:

?- freeze(X, member(X, [the(1), the(2)])), X = the(Y).

успешно, поставив следующий вопрос:

?- solve((freeze(X, member(X, [the(1), the(2)])), X = the(Y), true), [], L).

"Истина" необходима, чтобы в последний раз проверять проснувшиеся цели. Если L возвращается пустым, то все замороженные цели проснулись. В противном случае есть несколько ожидающих замороженных целей. Что иногда называют барахтанием.

Вышеприведенный прототип также приводит к естественной реализации сопрограмм через тонкие атрибуты, отмену /1 и некоторую небольшую поддержку интерпретатора в очереди внедрения цели. Я скоро напишу об этом где-нибудь еще.

до свидания

(*) https://www.complang.tuwien.ac.at/ulrich/iso-prolog/prologue

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