摘要:为了尽可能提升互通性,已经成为函数式编程库遵循的实际标准。与轻量级函数式编程的概念相反,它以火力全开的姿态进军的函数式编程世界。
原文地址:Functional-Light-JS
原文作者:Kyle Simpson-《You-Dont-Know-JS》作者
JavaScript 轻量级函数式编程 附录 C:函数式编程函数库关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTML 最坚实的梁柱;分享,是 CSS 里最闪耀的一瞥;总结,是 JavaScript 中最严谨的逻辑。经过捶打磨练,成就了本书的中文版。本书包含了函数式编程之精髓,希望可以帮助大家在学习函数式编程的道路上走的更顺畅。比心。
译者团队(排名不分先后):阿希、blueken、brucecham、cfanlife、dail、kyoko-df、l3ve、lilins、LittlePineapple、MatildaJin、冬青、pobusama、Cherry、萝卜、vavd317、vivaxy、萌萌、zhouyao
如果您已经从头到尾通读了此书,请花一分钟的时间停下来回顾一下从第 1 章到现在的收获。相当漫长的一段旅程,不是吗?希望您已经收获了大量新知识,并用函数式的方式思考你的程序。
在本书即将完结时,我想给你提供一些关于使用官方函数式编程函数库的快速指南。注意这并不是一个详细的文档,而是将你在结束“轻量级函数式编程”后进军真正的函数式编程时应该注意的东西快速梳理一下。
如果有可能,我建议你不要做重新造轮子这样的事情。如果你找到了一个能满足你需求的函数式编程函数库,那么用它就对了。只有在你实在找不到合适的库来应对你面临的问题时,才应该使用本书提供的辅助实用函数 —— 或者自己造轮子。
目录在本书第 1 章曾列出了一个函数式编程库的列表,现在我们来扩展这个列表。我们不会涉及所有的库(它们之中有许多重复的内容),但下面这些你应该有所关注:
Ramda:通用函数式编程实用函数
Sanctuary:函数式编程类型 Ramda 伴侣
lodash/fp:通用函数式编程实用函数
functional.js:通用函数式编程实用函数
Immutable:不可变数据结构
Mori:(受到 ClojureScript 启发)不可变数据结构
Seamless-Immutable:不可变数据助手
tranducers-js:数据转换器
monet.js:Monad 类型
上面的列表只列出了所有函数式编程库的一小部分,并不是说没有在列表中列出的库就不好,也不是说列表中列出的就是最佳选择,总之这只是 JavaScript 函数式编程世界中的一瞥。您可以前往这里查看更完整的函数式编程资源。
Fantasy Land(又名 FL)是函数式编程世界中十分重要的学习资源之一,与其说它是一个库,不如说它是一本百科全书。
Fantasy Land 不是一份为初学者准备的轻量级读物,而是一个完整而详细的 JavaScript 函数式编程路线图。为了尽可能提升互通性,FL 已经成为 JavaScript 函数式编程库遵循的实际标准。
Fantasy Land 与“轻量级函数式编程”的概念相反,它以火力全开的姿态进军 JavaScript 的函数式编程世界。也就是说,当你的能力超越本书时,FL 将会成为你接下来前进的方向。我建议您将其保存在收藏夹中,并在您使用本书的概念进行至少 6 个月的实战练习之后再回来。
Ramda (0.23.0)摘自 Ramda 文档:
Ramda 函数自动地被柯里化。
Ramda 函数的参数经过优化,更便于柯里化。需要被操作的数据往往放在最后提供。
我认为合理的设计是 Ramda 的优势之一。值得注意的是,Ramda 的柯里化形式(似乎大多数的库都是这种形式)是我们在第 3 章中讨论过的“松散柯里化”。
第 3 章的最后一个例子 —— 我们定义无值(point-free)工具函数 printIf() —— 可以在 Ramda 中这样实现:
function output(msg) { console.log( msg ); } function isShortEnough(str) { return str.length <= 5; } var isLongEnough = R.complement( isShortEnough ); var printIf = R.partial( R.flip( R.when ), [output] ); var msg1 = "Hello"; var msg2 = msg1 + " World"; printIf( isShortEnough, msg1 ); // Hello printIf( isShortEnough, msg2 ); printIf( isLongEnough, msg1 ); printIf( isLongEnough, msg2 ); // Hello World
与我们在第 3 章中的实现相比有几处不同:
我们使用 R.complement(..) 而不是 not(..) 在 isShortEnough(..) 周围新建一个否定函数 isLongEnough(..)。
使用 R.flip(..) 而不是 reverseArgs(..) 函数,值得一提的是,R.flip(..) 仅交换头两个参数,而 reverseArgs(..) 会将所有参数反向。在这种情景下,flip(..) 更加方便,所以我们不再需要使用 partialRight(..) 或其他投机取巧的方式进行处理。
R.partial(..) 所有的后续参数以单个数组的形式存在。
因为 Ramda 使用松散柯里化,因此我们不需要使用 R.uncurryN(..) 来获得一个包含所有参数的 printIf(..)。如果我们这样做了,就相当于使用 R.uncurryN(2, ..) 包裹 R.partial(..) 进行调用,这是完全没有必要的。
Ramda 是一个受欢迎的、功能强大的库。如果你想要在你的代码中实践 FP,从 Ramda 开始是个不错的选择。
Lodash/fp (4.17.4)Lodash 是整个 JS 生态系统中最受欢迎的库。Lodash 团队发布了一个“FP 友好”的 API 版本 —— "lodash/fp"。
在第 8 章中,我们讨论了合并独立列表操作(map(..)、filter(..) 以及 reduce(..))。使用“lodash/fp”时,你可以这样做:
var sum = (x,y) => x + y; var double = x => x * 2; var isOdd = x => x % 2 == 1; fp.compose( [ fp.reduce( sum )( 0 ), fp.map( double ), fp.filter( isOdd ) ] ) ( [1,2,3,4,5] ); // 18
与我们所熟知的 _. 命名空间前缀不同,“lodash/fp”将 fp. 定义为其命名空间前缀。我发现一个很有用的区别,就是 fp. 比 _. 更容易识别。
注意 fp.compose(..)(在常规 lodash 版本中又名 _.flowRight(..))接受一个函数数组,而不是独立的函数作为参数。
lodash 拥有良好的稳定性、广泛的社区支持以及优秀的性能,是你探索 FP 世界时的坚实后盾。
Mori (0.3.2)在第 6 章中,我们已经快速浏览了一下 Immutable.js 库,该库可能是最广为人知的不可变数据结构库了。
让我们来看一下另一个流行的库:Mori。Mori 设计了一套与众不同(从表面上看更像函数式编程)的 API:它使用独立的函数而不直接在值上操作。
var state = mori.vector( 1, 2, 3, 4 ); var newState = mori.assoc( mori.into( state, Array.from( {length: 39} ) ), 42, "meaning of life" ); state === newState; // false mori.get( state, 2 ); // 3 mori.get( state, 42 ); // undefined mori.get( newState, 2 ); // 3 mori.get( newState, 42 ); // "meaning of life" mori.toJs( newState ).slice( 1, 3 ); // [2,3]
这是一个指出关于 Mori 的一些有趣的事情的例子:
使用 vector 而不是 list(你可能会想用的),主要是因为文档说它的行为更像 JavaScript 中的数组。
不能像在操作原生 JavaScript 数组那样在任意位置设置值,在 vector 结构中,这将会抛出异常。因此我们必须使用 mori.into(..),传入一个合适长度的数组来扩展 vector 的长度。在上例中,vector 有 43 个可用位置(4 + 39),所以我们可以在最后一个位置(索引为 42)上写入 "meaning of life" 这个值。
使用 mori.into(..) 创建一个较大的 vector,再用 mor.assoc(..) 根据这个 vector 创建另一个 vector 的做法听起来效率低下。但是,不可变数据结构的好处在于数据不会进行克隆,每次“改变”发生,新的数据结构只会追踪其与旧数据结构的不同之处。
Mori 受到 ClojureScript 极大的启发。如果您有 ClojureScript 编程经验,那您应该对 Mori 的 API 感到非常熟悉。由于我没有这种编程经验,因此我感觉 Mori 中的方法名有点奇怪。
但相比于在数据上直接调用方法,我真的很喜欢调用独立方法这样的设计。Mori 还有一些自动返回原生 JavaScript 数组的方法,用起来非常方便。
总结JavaScript 不是作为函数式编程语言来特别设计的。不过其自身的确拥有很多对函数式编程非常友好基础语法(例如可作为变量的函数、闭包等)。本章提及的库将使你更方便的进行函数式编程。
有了本书中函数式编程概念的武装,相信你已经准备好开始处理现实世界的代码了。找一个优秀的函数式编程库来用,然后练习,练习,再练习。
就是这样了。我已经将我目前所知道的知识分享给你了。我在此正式认证您为“JavaScript 轻量级函数式编程”程序员!好了,是时候结束我们一起学习 FP 这部分的“章节”了,但我的学习之旅还将继续。我希望,你也是!
【上一章】翻译连载 | 附录 B: 谦虚的 Monad-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇
iKcamp原创新书《移动Web前端高效开发实战》已在亚马逊、京东、当当开售。
iKcamp官网:https://www.ikcamp.com
访问官网更快阅读全部免费分享课程:
《iKcamp出品|全网最新|微信小程序|基于最新版1.0开发者工具之初中级培训教程分享》
《iKcamp出品|基于Koa2搭建Node.js实战项目教程》
包含:文章、视频、源代码
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/92391.html
摘要:我称之为轻量级函数式编程。序众所周知,我是一个函数式编程迷。函数式编程有很多种定义。本书是你开启函数式编程旅途的绝佳起点。事实上,已经有很多从头到尾正确的方式介绍函数式编程的书了。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson - 《You-Dont-Know-JS》作者 译者团队(排名不分先后):阿希、blueken、brucecham、...
摘要:所以我觉得函数式编程领域更像学者的领域。函数式编程的原则是完善的,经过了深入的研究和审查,并且可以被验证。函数式编程是编写可读代码的最有效工具之一可能还有其他。我知道很多函数式编程编程者会认为形式主义本身有助于学习。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson - 《You-Dont-Know-JS》作者 关于译者:这是一个流淌着沪江血液...
摘要:就像我写书的过程一样,每个开发者在学习函数式编程的旅程中都会经历这个部分。类型在函数式编程中有一个巨大的兴趣领域类型论,本书基本上完全远离了该领域。在函数式编程中,像这样涵盖是很普遍的。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson-《You-Dont-Know-JS》作者 关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTML...
摘要:译者团队排名不分先后阿希冬青萝卜萌萌轻量级函数式编程附录下组合柯里化这一步是最棘手的。该片段中的组合函数被称为,而不是。上一章翻译连载附录上轻量级函数式编程你不知道的姊妹篇原创新书移动前端高效开发实战已在亚马逊京东当当开售。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson-《You-Dont-Know-JS》作者 关于译者:这是一个流淌着...
摘要:我不会把严格的称为轻量级函数式编程,它更像是一个顶级的技巧。实际上,我认为这是你掌握了轻量级函数式编程后可以做的最好的例证之一。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson-《You-Dont-Know-JS》作者 关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTML 最坚实的梁柱;分享,是 CSS 里最闪耀的一瞥;总结,是 ...
阅读 2844·2021-11-24 09:39
阅读 3461·2021-11-22 13:54
阅读 3352·2021-11-16 11:45
阅读 2357·2021-09-09 09:33
阅读 3118·2019-08-30 15:55
阅读 1218·2019-08-29 15:40
阅读 866·2019-08-29 15:19
阅读 3320·2019-08-29 15:14