- 小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
目录
Ramda主要特性- 主要风格
pointFreecurrypartial - 分支语句
R.ifElseR.when... - 分支语句
R.cond... - 函数组合
pipecompose... - 遍历:
map...
使用了多年的库,再次推荐给大家~
一 Ramda 主要特性
Ramda 主要特性如下
- Ramda 强调更加纯粹的函数式风格。数据不变性和函数无副作用是其核心设计理念。这可以帮助你使用简洁、优雅的代码来完成工作。
- Ramda 函数本身都是自动柯里化的。这可以让你在只提供部分参数的情况下,轻松地在已有函数的基础上创建新函数。
- Ramda 函数参数的排列顺序更便于柯里化。要操作的
数据通常在最后面。
最后两点一起,使得将多个函数构建为简单的函数序列变得非常容易,每个函数对数据进行变换并将结果传递给下一个函数。Ramda 的设计能很好地支持这种风格的编程。
二 主要风格
pointFree无参数风格- 柯里化 所有方法都支持柯里化
- 偏函数
partial
1) pointFree 无参数风格
Ramda 先接受函数参数,最后接受数据参数 柯里化和 “函数优先” 这两者相结合,使开发者在最终传入数据之前,能够以非常少的代码(通常为 “point-free” 风格,也即无参数风格)来组合函数。
例如
// Underscore/Lodash style:
var validUsersNamedBuzz = function(users) { // 参数
return _.filter(users, function(user) { // 参数
return user.name === 'Buzz' && _.isEmpty(user.errors); // 参数
});
};
// Ramda style:
var validUsersNamedBuzz = R.filter(R.where({name: 'Buzz', errors: R.isEmpty}));
2) 柯里化 所有方法都支持柯里化
也就是说,所有多参数的函数,默认都可以单参数使用。
自动柯里化使得 “通过组合函数来创建新函数” 变得非常容易。因为 API 都是函数优先、数据最后(先传函数,最后传数据参数),你可以不断地组合函数,直到创建出需要的新函数,然后将数据传入其中
关于柯里化的实现可以 参考 我的另一篇文章 高频面试题】函数柯里化的实现
function curry(fn){
if(fn.length <=1){return fn}
var returnFn = (...args) => {
//console.log(...args,typeof ...args);
if(fn.length === args.length){
//参数都传齐时
return fn(...args)
}else{
//参数没传齐时,就返回一个函数
return (...args2) => {
console.log(args2," ",args);
return returnFn(...args,...args2)
}
}
}
return returnFn
}
var add = (a,b,c,d) => a+b+c+d;
//包装add
var returnFn = curry(add);
// 递归传递参数给returnFn
var returnFnArrowFn = returnFn(1)(2)(3);
// 参数传齐,returnFn将参数传递给输入函数fn, 并调用fn
returnFnArrowFn(4);// 10
3) 偏函数 partial
允许多参数的函数接受一个数组,指定最左边的部分参数
var multiply2 = (a, b) => a * b;
var double = R.partial(multiply2, [2]);
double(2) // 4
var fn = (a, b, c, d) =>
a + b + c + d
var one = R.partial(fn, ['a']);
var all = R.partial(one, ['b']);
all('c', 'd');
'abcd'
三 分支语句 R.ifElse R.when
const incCount = R.ifElse(
R.has('count'),
R.over(R.lensProp('count'), R.inc),
R.assoc('count', 1)
);
incCount({}); //=> { count: 1 }
incCount({ count: 1 }); //=> { count: 2 }
// truncate :: String -> String
const truncate = R.when(
R.propSatisfies(R.gt(R.__, 10), 'length'),
R.pipe(R.take(10), R.append('…'), R.join(''))
);
truncate('12345'); //=> '12345'
truncate('0123456789ABC'); //=> '0123456789…'
四 分支语句 R.cond
一般用来代替
swith case或者 代替if...else if ...else if ...else...
const fn = R.cond([
[R.equals(0), R.always('water freezes at 0°C')],
[R.equals(100), R.always('water boils at 100°C')],
[R.T, temp => 'nothing special happens at ' + temp + '°C']
]);
fn(0); //=> 'water freezes at 0°C'
fn(50); //=> 'nothing special happens at 50°C'
fn(100); //=> 'water boils at 100°C'
五 函数组合 pipe compose...
1) pipe compose的使用
pipe
pipe函数的结果不是自动柯里化的
const f = R.pipe(Math.pow, R.negate, R.inc);
f(3, 4); // -(3^4) + 1 // -80
compose
// 3先传给inc,inc执行结果作为参数传给negate.
const f = R.compose(R.negate, R.inc); // 加1后取反
f(3); // -4
compose 输出的函数不会自动进行柯里化。
2) pipe compose的实现
参考我的另一篇文章 : 【高频面试题】compose和pipe的实现
六 遍历:map...
Ramdajs中的
map和js原生 map最大区别:是可以处理数组和对象,而原生的只可以处理数组.还有就是R.map是柯里化的
var double = x => x * 2;
R.map(double)([1, 2, 3])
// [2, 4, 6]
var double = x => x * 2;
R.map(double)({x: 1, y: 2, z: 3})
// {x: 2, y: 4, z: 6}
参考
总结
- 除了数据放在最后一个参数,Ramda 还有一个特点:所有方法都支持柯里化, 也就是说,所有
多参数的函数,默认都可以单参数使用。 - Ramdajs中的
map和js原生 map最大区别:是可以处理数组和对象,而原生的只可以处理数组.还有就是R.map是柯里化的 Ramda 强大的API很多,文章只列举一些,感兴趣的移步官网,哈哈,也可以和我多交流