我读过维基百科上关于响应式编程的文章。我还读过一篇关于函数式响应式编程的小文章。这些描述相当抽象。
函数式响应式编程(FRP)在实践中意味着什么? 反应式编程(相对于非反应式编程?)由什么组成?
我的背景是命令式/OO语言,所以与此范例相关的解释将受到赞赏。
我读过维基百科上关于响应式编程的文章。我还读过一篇关于函数式响应式编程的小文章。这些描述相当抽象。
函数式响应式编程(FRP)在实践中意味着什么? 反应式编程(相对于非反应式编程?)由什么组成?
我的背景是命令式/OO语言,所以与此范例相关的解释将受到赞赏。
当前回答
Andre Staltz的这篇文章是迄今为止我所见过的最好、最清楚的解释。
以下是文章中的一些引述:
响应式编程是使用异步数据流进行编程。 最重要的是,你会得到一个神奇的功能工具箱来组合、创建和过滤任何这些流。
下面是文章中精彩图表的一个例子:
其他回答
它是关于随着时间(或忽略时间)的数学数据转换。
在代码中,这意味着函数的纯洁性和声明性编程。
状态错误是标准命令式范例中的一个大问题。不同的代码位可能在程序执行的不同“时间”改变一些共享状态。这很难处理。
在FRP中,你描述了(就像在声明式编程中一样)数据如何从一种状态转换到另一种状态,以及触发它的是什么。这允许您忽略时间,因为您的函数只是对其输入作出反应,并使用它们的当前值创建一个新值。这意味着状态包含在转换节点的图(或树)中,并且在功能上是纯的。
这大大降低了复杂性和调试时间。
想想数学中的A=B+C和程序中的A=B+C之间的区别。 在数学中,你描述的是一种永不改变的关系。在一个程序中,它说“现在”a是B+C。但是下一个命令可能是b++,在这种情况下A不等于B+C。在数学或声明性编程中,A总是等于B+C,无论你在什么时候问。
因此,通过消除共享状态的复杂性并随时间改变值。你的程序更容易推理。
EventStream是一个EventStream +一些转换函数。
行为是一个EventStream +内存中的某个值。
当事件触发时,通过运行转换函数更新值。这产生的值存储在行为内存中。
行为可以被组合以产生新的行为,这些行为是对N个其他行为的转换。该组合值将在输入事件(行为)触发时重新计算。
由于观察器是无状态的,我们经常需要几个观察器来模拟一个状态机,就像在拖动示例中那样。我们必须保存所有相关观察者都可以访问的状态,比如上面的变量路径。”
引用自-弃用观察者模式 http://infoscience.epfl.ch/record/148043/files/DeprecatingObserversTR2010.pdf
Paul Hudak的书,The Haskell School of Expression,不仅是对Haskell的很好的介绍,而且还花了相当多的时间在FRP上。如果你是FRP的初学者,我强烈推荐它让你了解FRP是如何工作的。
还有一本看起来像是这本书(2011年出版,2014年更新)的新重写版——哈斯克尔音乐学院。
对我来说,这是关于符号的2个不同的含义=:
在数学中,x = sint的意思是,x是sint的另一个名字。所以写x + y和sin(t) + y是一样的。函数式响应式编程在这方面就像数学:如果你写x + y,它是用t在使用时的任何值来计算的。 在类c编程语言(命令式语言)中,x = sin(t)是一个赋值:它意味着x存储在赋值时所取的sin(t)的值。
Andre Staltz的这篇文章是迄今为止我所见过的最好、最清楚的解释。
以下是文章中的一些引述:
响应式编程是使用异步数据流进行编程。 最重要的是,你会得到一个神奇的功能工具箱来组合、创建和过滤任何这些流。
下面是文章中精彩图表的一个例子:
就像电子表格一样。通常基于事件驱动框架。
和所有的“范式”一样,它的新颖性是有争议的。
根据我对参与者的分布式流网络的经验,它很容易陷入节点网络状态一致性的普遍问题,即你最终会陷入很多振荡并陷入奇怪的循环中。
这是很难避免的,因为一些语义意味着引用循环或广播,并且当参与者网络收敛(或不收敛)在某些不可预知的状态时,可能会非常混乱。
类似地,尽管具有定义良好的边缘,但可能无法到达某些状态,因为全局状态偏离了解决方案。2+2可能等于4,也可能不等于4,这取决于2是什么时候变成2的,以及它们是否一直是这样。电子表格具有同步时钟和循环检测。分布式参与者通常不会。
一切都很有趣:)。