我现在正在大学读自学课程,并注意到我咬了一下比我能咀嚼的更多。该课程是关于Oz编程语言,我正在阅读一本关于它的电子书,试图更好地了解它,我正在尝试解决一些练习来测试我的理解。我一直坚持参加某项运动而且我不太清楚如何解决它。问题是:
实施端口。在第5章中我们介绍了端口的概念, 这是一个简单的沟通渠道。港口有运营 {NewPort S P},返回带有流S的端口P和{Send P X}, 它在端口P上发送消息X.从这些操作中可以清楚地看出 端口是有状态的非捆绑式ADT。对于本练习,请实施 使用第6.4节中的技术,以单元格表示端口。
关键词是有状态的非捆绑和细胞。我尝试使用以下方法实现端口行为:
declare
MyPort
MyStream
proc {NewPortEx ?S ?P}
P = {NewCell nil}
S = !!P %read only view on the cell
end
proc {SendEx P X}
P:=X|@P %extend the cell's content, a list, with X
end
in
{NewPortEx MyStream MyPort}
{Browse @MyStream}
{SendEx MyPort c}
{Browse @MyStream}
我的最后一步是添加一个包装器/解包器对以使ADT安全,但首先我希望功能正常工作。
这似乎做了正确的行为,但它并不像我想要的那样。我希望能够在没有{Browse MyStream}
的情况下拨打@
一次。我希望浏览器会显示firstSent|secondSent|_<future>
的内容,而不是按预期显示<Cell>
,我需要在每个Browse
之后调用Send
,输出显示为列表:[firstSent secondSent]
。
如果我从我阅读的理论中正确记得,这与预测与懒惰评估有关,分别导致(有限)列表与(无限)流。
我觉得我没有做得很好但是我对功能语言没有任何经验,有没有人可以帮助我制作一个用单元格实现的端口的例子? (基本上是您自己对现有NewPort
和Send
)
提前致谢
答案 0 :(得分:1)
流只是一个带有未绑定尾部的列表。例如。最初,列表只是一个未绑定的变量_。无论何时发送元素,尾部都绑定到一对新的,例如:
(1) Initially: S = _
(2) Send 1 to the port: S = 1|_
(3) Send 2 to the port: S = 1|2|_
etc.
除非您关闭端口,否则尾部始终保持未绑定状态。
现在您将单元格用作指向列表末尾的指针。最初,单元格指向S.然后,SendEx操作包含以下步骤:
(1) Read the current tail from the cell.
(2) Declare a new unbound variable that will serve as the new tail.
(3) Unify: current tail = X | new tail
(4) Store the new tail in the cell.
希望这有帮助。