【问题标题】:Is ReactiveX considered reactive programming? [closed]ReactiveX 被认为是反应式编程吗? [关闭]
【发布时间】:2016-06-09 08:31:54
【问题描述】:

来自ReactiveX introduction page

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

同时,来自Wikipedia's Functional Reactive Programming page,ReactiveX 被列在“实现”部分:

实现[编辑]

  • cellx,javascript 反应性的超快速实现
  • Elm,可编译为 HTML、CSS 和 JavaScript 的 FRP 语言
  • Ruby 中的星冰乐 FRP 实现
  • 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 实现
  • 在 C#、C++、Haskell(已弃用 [12])、Java、> Rust 和 Scala 中实现钠、FRP
  • 在 Haskell 中实现 Yampa FRP

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

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

【问题讨论】:

    标签: reactive-programming frp reactivex


    【解决方案1】:

    reactive-banana 库的作者在这里。

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

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

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

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

    • 首先,该语句最可能的解析是“行为是连续函数Time -> a”,这是不正确的:行为可以是连续的,例如它们可以是阶跃函数。相反,FRP 中的 Time 通常被视为实数,即值的连续体
    • 其次,完全有可能在时间离散的情况下使用 FRP。这不是 RP 的主要区别,而是您对值的操作是否具有明确定义的指称语义。

    【讨论】:

    • 您好,谢谢您的回复,您能解释一下您在代码块中放入的那些类型吗?
    • @TrungDQ 好吧,Time -> a 类型表示一个函数,其参数类型为Time,结果值类型为a。它可以解释为随时间变化的值。 [(Time, a)] 类型表示Time 类型值和a 类型值对的列表。它可以解释为在不同时间点发生的一组事件。
    【解决方案2】:

    据我了解,从 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], ... 所以ab[1] > ab[0] 应该始终为假。但是,在我的电脑上,如果我让这段代码运行一段时间,它确实会在某个时候结束it could take a while, try it yourself

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

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

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

    【讨论】:

      猜你喜欢
      • 2010-09-13
      • 2013-11-20
      • 2011-10-02
      • 2013-07-24
      • 2010-09-26
      • 1970-01-01
      • 2010-11-06
      • 1970-01-01
      • 2011-10-08
      相关资源
      最近更新 更多