如何相互依赖处理这两个信号?

时间:2014-01-27 15:47:01

标签: scala reactive-programming frp

我阅读Deprecating the Observer Pattern with Scala.React并发现反应式编程非常有趣。

但有一点我无法弄清楚:作者将信号描述为DAG(有向无环图)中的节点。那么如果你有两个信号(或事件源,或模型,w / e)相互依赖怎么办?即“双向绑定”,如网络前端编程中的模型和视图。

有时它只是不可避免的,因为用户可以更改视图,后端(例如异步请求)可以更改模型,您希望对方立即反映更改。

4 个答案:

答案 0 :(得分:3)

可以使用各种语义来处理反应式编程语言中的循环依赖性。看起来在scala.React中选择的那个是同步反应语言,特别是Esterel。你可以在Benveniste,A。的文章“12年后的同步语言”中对这种语义及其替代方案有一个很好的解释。 Caspi,P .;爱德华兹,S.A。; Halbwachs,N .; Le Guernic,P .; de Simone,R。可在http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=1173191&tag=1http://virtualhost.cs.columbia.edu/~sedwards/papers/benveniste2003synchronous.pdf获得。

答案 1 :(得分:2)

扫描完纸后,我找不到他们提到的必须是非循环的。没有什么可以阻止您在数据流/反应式编程中创建循环图。非循环图仅允许您创建管道数据流(例如Unix命令行管道)。

反馈和周期是数据流中非常强大的机制。没有它们,您只能使用您可以创建的程序类型。看看Flow-Based Programming - Loop-Type Networks


pagoda_5b

之后的第二篇帖子后进行修改

论文中的一个陈述让我注意到了......

  

对于正确排序的图表,此过程   单调地进行更高层次,从而确保数据   一致性,即没有毛刺。

对我说,Scala.React框架中不允许循环。两个节点之间的循环似乎会导致系统不断尝试永久地提高两个节点的级别。

但这并不意味着您必须在其框架内编码循环。可以从您想要观察的项目中获得一条路径,然后将另一条单独的路径返回到GUI。

对我而言,似乎总是过分强调编程系统完成并给出一个答案。循环使得很难确定何时终止。使用“被动”一词的图书馆倾向于订阅这个思维过程。但这只是冯·诺依曼计算机架构的结果......解决方程并返回 答案的重点。回避循环的图书馆似乎担心程序终止。

Dataflow不要求程序有正确答案或终止。由于此时的输入,答案就是这个时刻的答案。如果不需要,可以预期反馈和循环。数据流系统基本上只是一个不断在节点之间传递数据的大循环。要终止它,你就停止它。

数据流不必如此复杂。这是考虑编程的一种非常不同的方式。我建议您查看J. Paul Morison的书"Flow Based Programming",了解数据流的现场测试版本或my book(一旦完成)。

答案 2 :(得分:2)

在这里回复@Matt Carkci,因为评论不够

在文章 7.1 Change Propagation

  

我们的更改传播实现使用基于推送的方法,该方法基于拓扑排序依赖关系图。当传播转弯开始时,传播者将自上次转弯以来已经失效的所有节点放入优先级队列,该队列根据拓扑顺序,简要级别进行排序。节点。传播器将节点在最低级别上出列并对其进行验证,从而可能更改其状态并将其依赖节点(更高级别)放在队列上。传播器重复此步骤,直到队列为空,始终跟踪当前级别,这对于下面的级别不匹配变得很重要。对于正确排序的图形,该过程单调地进行到更高的水平,从而确保数据的一致性,即没有毛刺。

以及稍后 7.6 Level Mismatch

部分
  

因此,我们需要准备一个不透明的节点 n 来访问更高拓扑级别的另一个节点。在 n 评估期间读取的每个节点首先检查传播器维护的当前传播级别是否大于节点的级别。如果是,它将照常进行,否则会抛出包含对自身的引用的级别不匹配异常,该引用仅在主传播循环中捕获。然后,传播者通过首先将其级别更改为引发异常的节点之上的级别,将 n 重新插入传播队列(因为它的级别已更改)以便稍后提升 n 在同一回合进行评估,然后传递所有 n 的家属。

虽然没有提及任何拓扑约束(循环与非循环),但有些事情并不清楚。 (至少对我来说)

首先出现了如何定义拓扑顺序的问题。

然后实现表明,相互依赖的节点将通过上面解释的异常机制在评估中永远循环。

您怎么看?

答案 3 :(得分:2)

检查您的MVC知识。视图不会更新模型,因此不会向其发送信号。控制器更新模型。对于C / F转换器,您将有两个控制器(一个用于F控制,一个用于C控制)。两个控制器都会向单个模型发送信号(该模型将唯一的实际温度Kelvin存储在lossless format中)。该模型将信号发送到两个单独的视图(一个用于C视图,一个用于F视图)。没有周期。

根据@ pagoda_5b的答案,我会说你很可能有周期(7.6应该以性能为代价处理它),但你必须保证没有无限回归。例如,您可以让控制器也从模型接收信号,只要您保证接收到所述信号从未导致信号被发送回模型。

我认为以上是一个很好的描述,但它使用非FRP风格的“信号”一词。上面的“信号”实际上就是消息。如果7.1中的描述正确且完整,则信号图中的循环将始终导致无限回归,因为处理节点的依赖性将导致节点被处理,反之亦然,ad inf。

正如@Matt Carkci所说,FRP框架允许循环,至少在有限的范围内。它们要么不是基于推的,要么以有趣的方式使用非严格性,强制单调性,要么引入“人为”延迟,以便当信号图在时间维度上扩展(将其转换为值图)时,周期消失。