原文:Why I cannot say FRP but I just did
一个有用的缩写词与过度保护的父母的故事。
函数响应式编程(Functional Reactive Programming,FRP)是一个越来越流行的缩写词。响应式编程和函数式编程都是真正有用的术语,它们传达的思想没有正式严谨的定义。然而,FRP 是一个极端严格的术语,它是 20 年前从数学上定义的编程技术。
人们松散地使用 FRP 来指代函数式编程与响应式编程相结合的技术。然而,他们都错了。这种挑剔的术语伤害了开发者社区,带来了混乱和对这 3 个字母发音的恐惧。我已经多次看到这种混乱的情况,我认为将 FRP 限制在它最初的严格语义上并不能帮助我们交流编程思想。
我相信 FRP 应该是一个传达理念的术语,就像函数式编程和反应式编程那样。
函数式(Functional)
函数式编程是一种将计算表示为对数学表达式求值的范式。在这种范式中,我们避免了有副作用的函数和易变的数据。我所想到的大多数编程语言都提供了一种编写纯数学函数的方法,例如,square(x)
函数。在某种程度上,函数式范式可以应用于任何语言,通过使用纯函数和避免(用约定或类型系统)可变数据和副作用。
Haskell 是函数式编程的极致体现,但它不是函数式技术的唯一载体。Clojure(和其他基于 LISP 的语言)、OCaml、F# 是几个值得一提的函数式编程语言。
函数式技术无处不在,把 "函数式编程" 这个术语仅仅局限于 Haskell 是不公平的。这是一个即使没有严格的数学也能理解和应用的想法。
反应式(Reactive)
尽管 "反应式编程" 并没有一个广为人知的准确定义,但它作为一个指代可监听信号、数据流和电子表格式计算的术语仍然很有用(已经超过 20 年了!)。
反应式编程在 1989 年的一篇论文中首次被提及的。它是用文字模糊地定义的,而不是数学上的严格定义:
变换式程序从一组给定的输入中计算结果;[...] 交互式程序以自己的速度与用户或其他程序交互 [...]。反应式程序也与环境保持持续的互动,但其速度由环境决定,而不是由程序本身决定。[...] 实时程序通常是反应式的。
从那时起,就有了反应式编程的其他定义 [1] [2] [3],但它们往往与可以观察到的事件流或可以对其他事件流做出反应的想法相关。
FRP 是一个被禁止的术语
鉴于上述反应式和函数式的含义,把 "函数响应式编程" 作为一种范式或思想来谈论是有意义的,在这种范式或思想中,你使用可监听的事件流(或"信号")来构建应用程序,使用纯函数来创建和组合它们。但是,这并不是 FRP 在从太阳起的第三块石头上首次被说出时的具体而准确的含义。
"原始 FRP" 是指使用行为和事件的指称和时间连续性函数式编程。
原始 FRP 的另一个术语是表示性、时间连续性编程(DCTP)。任何偏离 FRP 先驱 Conal Elliot 定义的一毫米的东西都是术语上的罪过。
Conal Elliott 在 Twitter 上
我指的是精确/严格的规范,而不是挥手示意。这是我对几乎所有现代的所谓"FRP"系统的不满之一。
Conal Elliott on Twitter
我对大多数所谓的"FRP"系统的另一个主要不满是放弃了最初的原则,即时间连续性。
Conal Elliott on Twitter
我想知道人们是如何把 Rx、RAC 及同类产品视为 #FRP 的,以及这些想法/信念是如何传播的。
Conal Elliott on Twitter
@mattpodwysocki @raimohanska @ph1 和 Bacon 等人并没有实现 FRP 的想法,它有一个精确的(impl-independent)表示。
Conal Elliott on Twitter
@tacticalgrace 大多数现代"FRP"系统也忽略了精确的指称,留下了不知道是什么的语义鼠窝而未被发现。
Conal Elliott on Twitter
@crstry 尽情享受! 尽量不要被"FRP"标签的现代、分散/模糊的使用所欺骗。我很乐意回答问题。
Conal Elliott on Twitter
@andrestaltz 这是关于FRP的基本原则(指称性和连续性)。Rx、Bacon 和 Elm 缺乏这两点。@mattpodwysocki @slashdotpeter
如果不遵循指示性和时间连续性的要求,Conal 就会努力避免对 FRP 的提及,这很无情。这背后的原因是什么?
人们猜测框架的 "FRP 分类" 将是一个有意义的分类,其饼状图大致如此。
人们期望 FRP 的分类是怎样的,是一个饼状图
上述情况完全不是现实的情况。原始的 FRP 在 Haskell 社区中是一个小众( Haskell 本身就是一个小众语言)。真正的饼状图看起来更像这样。
对 FRP 框架的分类更准确的认知
Conal 在 StackOverflow 上的回答链接到一个 Haskell 页面,列出了一些库。你会猜想至少这些库一定是真正的 FRP。这是不正确的。Sodium 是该列表中的第一个库,然而这个论坛的讨论表明,Sodium 缺乏真正的 FRP 所需要的精确指称。任何洒在上面的指称都意味着一种错误的方法,因为真正的 FRP 是指称优先的。
这使得 FRP 这个词对大多数程序员来说基本上是无用的,因为它只与一个小众领域有关。
我们有什么选择呢?
鉴于 "函数式" 和 "响应式" 经常一起用来描述一个解决方案或库,我开始使用 "F&RP"(它也可能是 "RFP" 或 "R&FP")。
André Staltz on Twitter
2015年2月5日:我在此正式建立一个新的缩写。F&RP:函数和响应式编程。(!=FRP)
当我认识到 FRP 是一个传达理念的术语,而不是一种规范时,我并不孤单。
Tenor Biel on Twitter
@conal 无意冒犯,但你应该把你对 FRP 的含义和更常见的含义分开:事件发射器是可折叠的应用程序(Event emitters are Foldable Applicatives)。
Yaron Minsky on Twitter
@conal 为什么离散版 "不是FRP"?分类应该在世界的关节处进行切割,它们似乎更相似而不是不同。
Manuel Chakravarty on Twitter
@conal 恕我直言,您选择了一个相当笼统的术语,所以通用的解释很常见,我并不感到惊讶。
Ben Christensen on Twitter
@daverstevens @tlockney 是的,这就是我在了解历史之前就开始使用 FRP 的原因......反应式风格 + 函数式风格 == FRP ......但没有。
Juha Paananen on Twitter
@mattpodwysocki @ph1 我认为 FRP 是一种思维方式。框架只是实现想法的方法。会继续得罪人的。很抱歉 :)
Elm 的创造者 Evan Czaplicki 在 Strangeloop 做了一个很好的演讲,对 "FRP" 的不同口味进行了分类,尽管按照保守派的说法这是一个悖论。
英语不是一个严格的类型系统
英国语言的发展和继续演变。我们使用词语来表达意思,但我们也会出于多种原因对词语和它们的含义进行延伸和变异。这个过程是人类可读的,也是不可避免的。
作为人类,我们想要谈论想法,而名字是表达这些想法的好方法。正如 Evan 的上述演讲所示,有多种工具(Fran, Yampa, Elm, Reactive Banana, Reactive Extensions, Bacon.js, ReactiveCocoa, Sodium)都有一个共同的想法:功能可控的信号。通过给一个共同的想法命名,我们使交流变得更容易。
我们应该给这个共同的想法起什么名字呢?RFP?F&RP?R&FP?这些都没有 FRP 那么广泛,对很多人来说,FRP 已经传达了可听和功能可控的事件流的概念。
我们要做什么?
讽刺的是,我实际上会采纳 Conal Elliott 的建议,他在 StackOverflow 的回答中说了一句:
为了减少混乱,我希望看到 "函数响应式编程" 一词被更准确和描述性的"指称性,时间连续性编程"(DCTP)"所取代。
原来的 FRP 变成了 DCTP,FRP 可以模糊地用于函数化的信号。
讨厌的人要讨厌,我宣布 Reactive Extensions 就是 FRP。