如何在Prolog中编写/编辑自己的协程?
我想在Prolog中构建我自己的协同程序。如何在Prolog中编写/编辑自己的协程?,prolog,freeze,coroutine,prolog-coroutining,Prolog,Freeze,Coroutine,Prolog Coroutining,我想在Prolog中构建我自己的协同程序。 我想添加一些额外的功能。一个可能的解决方案是使用一些Prolog系统和Logtalk提供的术语扩展机制来重写调用,例如,freeze/2谓词来执行您想要的额外步骤。但是,必须小心,不要将对谓词的调用扩展到调用同一谓词的另一个目标,因为目标扩展是递归应用的,直到达到一个定点为止。术语扩展机制的Logtalk实现通过使用编译器旁路控制结构{}/1很容易避免这个陷阱(具有可移植性的额外优势,因为您可以在大多数Prolog系统中使用Logtalk)。一个愚蠢的
我想添加一些额外的功能。一个可能的解决方案是使用一些Prolog系统和Logtalk提供的术语扩展机制来重写调用,例如,
freeze/2
谓词来执行您想要的额外步骤。但是,必须小心,不要将对谓词的调用扩展到调用同一谓词的另一个目标,因为目标扩展是递归应用的,直到达到一个定点为止。术语扩展机制的Logtalk实现通过使用编译器旁路控制结构{}/1
很容易避免这个陷阱(具有可移植性的额外优势,因为您可以在大多数Prolog系统中使用Logtalk)。一个愚蠢的例子是:
:- 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文档和示例
可能有一种清洁的方式,我不知道使用Prolog系统自己的术语扩展机制实现也会这样做。有人吗?为合作项目编写一个普通的解释器应该在每门Prolog课程的教学清单上。这很简单,在这里你可以看到普通的香草解释器,简化的:
% solve(+Term)
solve(true).
solve((A,B)) :- solve(A), solve(B).
solve(H) :- clause(H, B), solve(B).
现在对于协同路由,在通过freeze/2暂停目标的意义上,只需添加一个额外的输入输出参数对和延迟的目标,有关select/3的规范,请参见(*):
您可以使用上面的普通解释器来研究不同的唤醒策略。我不确定它是否捕获了现有的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).
需要“true”来检查最后一次醒来的目标。如果L是空的,那么所有冻结的目标都会被唤醒。否则就会有一些悬而未决的冻结目标。这有时被称为挣扎
上述原型还通过精简属性、undo/1和目标注入队列对解释器的一些小支持,自然地实现了协同路由。我很快会把这件事发到其他地方
再见
(*)
好的。你能解释一下冷冻是如何工作的吗。我真的希望模拟Prolog执行的操作。查看有关属性变量的Prolog系统文档部分。我是否可以使用目标扩展来扩展=/2的功能?简短回答,是的。只要您使用的Prolog系统提供术语扩展机制,您就应该能够为
goal\u expansion/2
定义子句,将调用扩展到正在编译的源文件上,例如=/2
。是否您发布的代码不起作用?至少我的堆栈用完了。例如,在这里可以找到其他元解释器,例如第167页:
?- 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).