我正在通过阅读 DrBoolean 的 book 来学习 JavaScript FP .
我四处寻找函数式编程库。我找到了 Ramda 和 Folktale。两者都声称是函数式编程库。
但它们是如此不同:
实际上我发现了更多的库,它们似乎都属于两类。 Underscore 和 lodash 就像 Ramda。梦幻之地,自由幻想就像民间故事。
这些非常不同的库都可以称为功能库吗?如果是,是什么使每个库都成为功能库?
最佳答案
功能特点
函数式编程或函数库的定义没有明确的界限。 Javascript 内置了函数式语言的一些特性:
其他一些可以在 Javascript 中小心完成:
还有一些是 ES6 的一部分,现在部分或完全可用:
还有很多其他的确实超出了 Javascript 的正常范围:
然后,一个库可以挑选并选择它试图支持的功能类型,并且仍然可以合理地称为“功能性”。
梦幻乐园规范
Fantasy-land是许多标准类型的规范,从数学范畴论和抽象代数移植到函数式编程,类型如 Monoid , Functor , 和 Monad .这些类型相当抽象,并且可能扩展了更熟悉的概念。例如,仿函数是容器,可以是
map
用函数遍历,数组的方式可以是map
使用 Array.prototype.map
完成.民间故事
Folktale是实现 Fantasy-land 规范各个部分的类型集合和一小部分配套实用程序函数。这些类型类似于 Maybe , Either , Task (非常类似于其他地方称为 Future 的东西,并且是 Promise 的更合法的表亲)和 Validation
Folktale 可能是 Fantasy-land 规范最著名的实现,并且备受推崇。但是没有明确的或默认的实现; Fantasy-land 只指定抽象类型,当然一个实现必须创建这样的具体类型。 Folktale 声称自己是一个函数式库,这一点很明确:它提供了函数式编程语言中常见的数据类型,这些类型使得以函数式方式编程变得更加容易。
这个例子,来自 Folktale documentation ( 注意 :不在最新版本的文档中),显示了它的使用方式:
// We load the library by "require"-ing it
var Maybe = require('data.maybe')
// Returns Maybe.Just(x) if some `x` passes the predicate test
// Otherwise returns Maybe.Nothing()
function find(predicate, xs) {
return xs.reduce(function(result, x) {
return result.orElse(function() {
return predicate(x)? Maybe.Just(x)
: /* otherwise */ Maybe.Nothing()
})
}, Maybe.Nothing())
}
var numbers = [1, 2, 3, 4, 5]
var anyGreaterThan2 = find(function(a) { return a > 2 }, numbers)
// => Maybe.Just(3)
var anyGreaterThan8 = find(function(a) { return a > 8 }, numbers)
// => Maybe.Nothing
lambda
Ramda (免责声明:我是作者之一)是一种非常不同类型的库。它不会为您提供新类型。1 相反,它提供了一些功能,以便更轻松地对现有类型进行操作。它是围绕将较小的函数组合成较大的函数、处理不可变数据、避免副作用的概念而构建的。
Ramda 尤其适用于列表,但也适用于对象,有时也适用于字符串。它还以与 Folktale 或其他 Fantasy-land 实现互操作的方式委派了许多调用。例如,Ramda 的
map
功能,操作与 Array.prototype
上的类似, 所以 R.map(square, [1, 2, 3, 4]); //=> [1, 4, 9, 16]
.但是因为Folktale的Maybe
实现梦幻之地Functor
spec,也指定了map,你也可以使用Ramda的map
用它:R.map(square, Maybe.Just(5)); //=> Maybe.Just(25);
R.map(square, Maybe.Nothing); //=> Maybe.Nothing
Ramda 声称自己是一个函数式库,因为它可以轻松组合函数,永远不会改变您的数据,并且只呈现纯函数。 Ramda 的典型用法是通过组合较小的函数来构建更复杂的函数,如 philosphy of Ramda 上的一篇文章所示。
// :: [Comment] -> [Number]
var userRatingForComments = R.pipe(
R.pluck('username') // [Comment] -> [String]
R.map(R.propOf(users)), // [String] -> [User]
R.pluck('rating'), // [User] -> [Number]
);
其他图书馆
Actually I found more libraries, they all seem fall into the two categorys. underscore, lodash are very like Ramda. Fantasy-land, pointfree-fantasy are like folktale.
这并不准确。首先,Fantasy-land 只是一个规范,图书馆可以决定为各种类型实现。 Folktale 是该规范的众多实现之一,可能是最全面的实现,当然也是最成熟的实现之一。 Pointfree-fantasy和 ramda-fantasy是其他的,还有many more .
Underscore和 lodash从表面上看,它们与 Ramda 相似,因为它们是抓包式库,提供了大量功能,但与 Folktale 之类的东西相比,内聚性要低得多。甚至特定功能也经常与 Ramda 重叠。但在更深层次上,Ramda 与那些库有着非常不同的关注点。 Ramda 的近亲可能是像 FKit 这样的库。 , Fnuc , 和 Wu.js .
Bilby属于它自己的一个类别,提供了许多工具,例如 Ramda 提供的工具和一些与 Fantasy-land 一致的类型。 (Bilby 的作者也是 Fantasy-land 的原作者。)
您的来电
所有这些库都有权被称为功能性的,尽管它们在功能方法和功能 promise 程度方面差异很大。
其中一些库实际上可以很好地协同工作。 Ramda 应该可以很好地与 Folktale 或其他 Fantasy-land 实现配合使用。由于它们的关注点几乎没有重叠,因此它们确实不冲突,但 Ramda 所做的足以使互操作相对顺畅。对于您可以选择的其他一些组合,这可能不太正确,但是 ES6 更简单的函数语法也可能会减轻集成的痛苦。
库的选择,甚至是使用的库风格,将取决于您的项目和您的偏好。有很多不错的选择可供选择,而且数量还在增长,其中许多正在大大改进。现在是在 JS 中进行函数式编程的好时机。
1嗯,有一个副项目,ramda-fantasy做一些类似于 Folktale 所做的事情,但它不是核心库的一部分。
关于javascript - 为什么民间故事和 lambda 如此不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33027305/