22

ReactiveX 介绍页面

它有时被称为“函数式反应式编程”,但这是用词不当。ReactiveX 可能是函数式的,也可能是响应式的,但“函数式响应式编程”是另一种动物。主要区别之一是函数式反应式编程对随时间连续变化的值进行操作,而 ReactiveX 对随时间发出的离散值进行操作。

同时,从Wikipedia 的功能响应式编程页面,ReactiveX 列在“实现”部分:

实现[编辑]

  • cellx,JavaScript 反应性的超快速实现
  • Elm,可编译为 HTML、CSS 和 JavaScript 的 FRP 语言
  • Frappuccino FRP 在 Ruby 中的实现
  • Flapjax,JavaScript 中的行为/事件 FRP 实现
  • Reactive.jl,Julia 中的 FRP 实现
  • ReactiveX、FRP 以多种语言实现,包括 Java、JavaScript、Python、Swift 等等
  • Haskell 中的响应式香蕉 FRP 实现
  • 用 Swift 和 Objective-C 实现的 ReactiveCocoa FRP
  • 用纯 Swift 实现的 ReactiveKit FRP
  • Haskell 中的 Reflex FRP 实现
  • Scala(和 Scala.js)中的 Scala.Rx FRP 实现
  • Sodium、C#、C++、Haskell(已弃用 [12])、Java、> Rust 和 Scala 中的 FRP 实现
  • Haskell中的Yampa FRP实现

我很了解 ReactiveX 是做什么的,也对“反应式编程”和“函数式反应式编程”做了一些研究,但我仍然无法区分它们之间的关系。

事实上,我有点相信 Wikipedia 页面用词不当,或者错误地在“实现”部分列出了示例,因为我知道cellxReactiveX(都在示例中列出)是为了解决完全不同的问题而构建的。

4

2 回答 2

20

反应香蕉库的作者在这里。

函数式反应式编程 (FRP) 和反应式编程 (RP) 之间的主要区别在于前者具有明确定义的指称语义,通常从类型中获得

type Behavior a  ~=  Time -> a
type Event    a  ~=  [(Time, a)]

而后者没有明确定义的指称语义。特别是,我知道的所有 RX 实现都存在合并事件流是不确定的问题:当流包含同时发生的事件时,有时一个事件会在另一个事件之前合并,有时会反过来。

此外,“FRP 对随时间不断变化的值起作用”的说法既有点不正确,也不是关键区别:

  • 首先,该语句最可能的解析是“行为是连续函数Time -> a”,这是不正确的:行为可以是连续的,例如它们可以是阶跃函数。相反,真实的情况是,Time在 FRP 中通常被视为实数,即值的连续统一体
  • 其次,完全有可能拥有时间离散的 FRP。这不是 RP 的关键区别,而是关于您对值的操作是否具有明确定义的指称语义。
于 2016-02-26T11:03:59.277 回答
7

据我了解,从 ReactiveX(又名 RX)的角度来看,根本不可能同时发生两个事件。这些只是在内部按订阅顺序依次触发的回调。RX 不“管理”时间。

从纯 FRP 程序员的角度来看,RX 可以表现得相当疯狂。考虑以下 RXJS 代码:

const xs = Rx.Observable
    .interval(0)
  //.share();

xs.combineLatest(xs, (a,b) => [a,b])
    .filter(ab => ab[1] > ab[0])
    .take(1)
    .subscribe(ab => alert(ab));

xs是一个尽可能快地触发的冷可观察区间。由于xs.combineLatest(ys, f)总是xs先订阅,然后订阅ys,因此您会期望xs.combineLatest(xs, (a,b) => [a,b])生成[0,0], [1,0], [1,1], [2,1], ...Soab[1] > ab[0]应该始终为 false。但是,在我的电脑上,如果我让这段代码运行一段时间,它确实会在某个时候结束,这可能需要一段时间,你自己试试

这是因为xs它是一个可观察对象:每个订阅都interval将创建一个独立运行的周期性计时器。这些计时器可以并且会在某些时候以不同的顺序触发(尤其是在 .NET 等多线程环境中)

如果我们注释掉这一//share行,使得xs hot,序列永远不会完成,就像[0,0], [1,0], [1,1], ... ,[i,i-1],[i,i]...现在确定性地生成的那样。这是因为一个热门的 observable 共享一个订阅。在这种情况下,只创建一个计时器。

在真正的 FRP 系统中,这种行为将是确定性的。但是,如果您真的要在真实 FRP 系统中连接到不同的硬件计时器,您也会得到与 RX 相同的行为,因为这些外部事件将以随机顺序触发,当然除非两个计时器完全同步

于 2016-02-29T22:41:01.650 回答