如何写/在序言编辑自己的协同程序?(How to write/edit own coroutines

2019-10-20 02:19发布

我想建立自己的协同程序中的Prolog。 我想添加一些额外的功能。

Answer 1:

一个可行的办法是使用一些Prolog的系统提供的术语展开机构和Logtalk重写调用例如在freeze/2谓词做你想要额外的步骤。 我们必须要小心,但是,不扩展到谓词调用到调用相同的谓词为目标,扩展递归应用,直到达到定点另一个目标。 所述Logtalk实施术语-膨胀机构的可以很容易地避免这种陷阱(可移植性的附加优点,因为可以用最Prolog的系统使用Logtalk)通过使用一个编译器旁路控制构建体, {}/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的系统自己长期展开机构实施做同样的。 任何人?



Answer 2:

写香草解释为协同程序应该是每一个序言课程的教学名单上。 这是很简单的,在这里你看到正常的香草解释,简化为:

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

现在对于corouting,在通过冷冻/ 2悬浮目标的意义上,仅仅增加一个额外的输入输出参数对与延迟的目标,对于选择/ 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



文章来源: How to write/edit own coroutines in Prolog?