万物皆可柯里化的 Ramda.js

简介: 本篇, 要讲的不是 RxJS,而是另外一个函数式编程库 Ramda.js ,它同样也可以与 loadsh 对比理解,不过它的设计思路又不同了,它最大的特点是:所有函数都可以柯里化传参!以此来践行函数式编程思想。

我们前段时间写过好几篇关于 RxJS 的文章,RxJS api 操作符理解起来确实比较复杂,RxJS 是函数式编程中的 lodash 库,它消除了“时序”而带来的困扰,它核心思想是:函数式 + 响应式。


本篇, 要讲的不是 RxJS,而是另外一个函数式编程库 Ramda.js ,它同样也可以与 loadsh 对比理解,不过它的设计思路又不同了,它最大的特点是:所有函数都可以柯里化传参!以此来践行函数式编程思想。

image.png


往下看,后面我们就能明白:Ramda 所有 Api 都能柯里化的意义所在。


Function first,Data last



在 lodash 中,我们是这样写的,

var square = n => n * n;
_.map([4, 8], square)


参数在前,执行函数在后。


而在 Ramda 中,强调:函数在前,参数在后


这样做有什么好处呢?

就是为了更好实现:柯里化。柯里化只需要参数一个一个的在后追加

var R = require('ramda');
R.map(square, [4, 8])
// 等同于
var R = require('ramda');
R.map(square)([4, 8])


再举个栗子:

var R = require('ramda');
const odd = x => x%2 === 1
const data = [3, 5, 6];
R.filter(odd, data); // [3, 5]
// 等同于
R.filter(odd)(data); // [3, 5]
// 也可以延迟调用
const filter1 = R.filter(odd);
// filter1 等待参数的传入
// 后续再传入 data
const filter2 = filter1(data)


如果不借用 Ramda.js , 需要自行实现柯里化,就会显得麻烦:


const _curry = f => a => b => f(a, b)
const odd = x => x%2 === 1
const _filter = _curry( (fn, arr) => arr.filter(fn) );
_filter(odd)([3,5,6]) // [3, 5]


Ramda 非常强调:R.api(fn, data) 这样的范式;


API



来看看 Ramda 有哪些神奇的、好用的、常用的 API~

  • map


map 让每个成员依次执行通过某个函数;

const double = x => x * 2;
R.map(double, [1, 2, 3]); //=> [2, 4, 6]
R.map(double, {x: 1, y: 2, z: 3}); //=> {x: 2, y: 4, z: 6}


  • filter

用于过滤;

const isEven = n => n % 2 === 0;
R.filter(isEven, [1, 2, 3, 4]); //=> [2, 4]
R.filter(isEven, {a: 1, b: 2, c: 3, d: 4}); //=> {b: 2, d: 4}


  • add

求和;

R.add(2, 3);       //=>  5
R.add(7)(10);      //=> 17


  • multiply

求积;

R.multiply(2)(5)  // 10


  • compose

函数组合,从右到左;

R.compose(Math.abs, R.add(1), R.multiply(2))(-4)
// |-4*2 + 1|,等于 7


  • pipe

函数组合,从左到右;

var negative = x => -1 * x;
var increaseOne = x => x + 1;
var f = R.pipe(Math.pow, negative, increaseOne)(3,4);
// -(3^4) + 1 ,等于 -80


  • curry

将多个参数转换为单个参数

const addFourNumbers = (a, b, c, d) => a + b + c + d;
const curriedAddFourNumbers = R.curry(addFourNumbers);
curriedAddFourNumbers(1, 2)(3)(4)


Ramda 还有其它丰富的 api,也可以结合 compose/pipe 自定义特定功能函数,用这些方法来简化程序,让代码变成函数式风格;

以上的例子都可在 jsrun.net/DTNKp/edit 可以在线运行测试;

更多 Ramda api 可见文档:ramda.cn/


相关文章
|
6月前
|
JavaScript 前端开发
JS 偏函数、函数柯里化~
该文章介绍了JavaScript中偏函数和函数柯里化的概念、实现方法和使用场景,通过代码示例展示了如何创建预设参数的函数以及如何将多参数函数转换成单参数函数的链式调用。
29 0
JS 偏函数、函数柯里化~
|
7月前
|
自然语言处理 JavaScript 前端开发
探析JS作用域
【8月更文挑战第2天】探析JS作用域
43 11
|
前端开发 JavaScript Serverless
前端祖传三件套JavaScript的函数之匿名函数
在JavaScript中,函数是实现各种功能和业务逻辑的基本手段。除了常规的函数声明和函数表达式外,JavaScript还支持匿名函数的定义方式。在这篇文章中,我们将介绍JavaScript中的匿名函数,以及其使用方法和注意事项
124 0
|
JavaScript
JS三座大山之1—原型和原型链
本期介绍原型、原型链和 class。包括 class ,继承,原型,原型链,instanceof。原型是 “JS 三座大山” 之一,原型和原型链也是必考知识点
178 1
JS三座大山之1—原型和原型链
|
Web App开发 缓存 前端开发
✨从柯里化讲起,一网打尽 JavaScript 重要的高阶函数
✨从柯里化讲起,一网打尽 JavaScript 重要的高阶函数
|
JavaScript Go
重温js——执行上下文
在函数的那一张中,提到了全局环境和局部环境的概念,就是说在函数的执行过程中,函数内部的环境和外面是独立的,只是说函数内部可以使用外面全局环境的变量或者在调用全局函数的方法。在此,来总结一下js的执行环境。
重温js——执行上下文
|
JavaScript
重温js——原型和原型链
我们在前文说到,所有的对象都是通过new 函数来创建的,所有的函数也都是对象 . 那么问题来了,Function也是一个函数,那么他是怎么来的呢?(这个问题是不是类似有点像先有鸡和先有蛋的感觉)但是Function函数是在js引擎启动的时候,就直接把Function放入到内存中的.
重温js——原型和原型链
|
JavaScript
重温js——函数基础
函数的作用,减少重复代码,实现代码的解耦。把某个功能点给抽离出来。使得代码阅读增加
重温js——函数基础
|
JavaScript
重温js——构造函数基础
在上面的代码中,我们可以创建多个对象,使用函数的方式来创建的对象。(但是这两个对象是不一样的,每一次都创建一个新的对象)可以方便许多,除了上面的方法外,还有一种构造函数的方式来创建对象。
重温js——构造函数基础
|
JavaScript
JS查漏补缺——柯里化
JS查漏补缺系列是我在学习JS高级语法时做的笔记,通过实践费曼学习法进一步加深自己对其的理解,也希望别人能通过我的笔记能学习到相关的知识点。这一次我们来了解柯里化
120 0