如何在 Prolog 中编写/编辑自己的协程?

Ric*_*rdo 2 freeze prolog coroutine prolog-coroutining

我想在 Prolog 中构建我自己的协程。我想添加一些额外的功能。

Tra*_*ers 5

为协程编写一个普通的解释器应该在每门 Prolog 课程的教学清单上。这很简单,在这里你可以看到普通的香草解释器,简化了:

% solve(+Term)
solve(true).
solve((A,B)) :- solve(A), solve(B).
solve(H) :- clause(H, B), solve(B).
Run Code Online (Sandbox Code Playgroud)

现在对于 coouting,在通过 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).
Run Code Online (Sandbox Code Playgroud)

您可以使用上面的 vanilla 解释器来研究不同的唤醒策略。我不确定它是否捕获了现有的 Prolog 系统。但是您可以运行以下示例:

?- freeze(X, member(X, [the(1), the(2)])), X = the(Y).
Run Code Online (Sandbox Code Playgroud)

成功,通过提出以下问题:

?- solve((freeze(X, member(X, [the(1), the(2)])), X = the(Y), true), [], L).
Run Code Online (Sandbox Code Playgroud)

需要“,真”来检查最后一次唤醒目标。如果 L 返回空,则所有冻结的目标都被唤醒。否则有一些悬而未决的冻结目标。这有时被称为挣扎。

上面的原型还通过瘦属性、undo/1 和目标注入队列对解释器的一些小支持导致了协程的自然实现。我很快会在其他地方发布这个。

再见

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