谈谈函数式编程curry
Curry概念
The concept is simple: You can call a function with fewer arguments than it expects. It returns a function that takes the remaining arguments.
当你调用一个函数的时候,传入的参数小于函数预期的个数时候它将返回一个新的函数,再来调用剩下的那些参数。
函数预期的参数个数其实就是函数的length属性所返回的个数。其中不包括(ES6的剩余参数)。
简单的实现
const add = x => y => x + y;
const increment = add(1);
const addTen = add(10);
increment(2); // 3
addTen(2); // 12
其中关键点就在于利用闭包来将参数收集起来。
curry有什么用
说实话当我第一次学习的时候,那已经是好几个月之前的事情了,当时看了下和上面代码类似的例子,也能看懂概念和原理。不过还是由于处于初学的状态加上没有感受过中大型项目的洗礼(现在也没233)开发经验不足,认为这个curry好像没啥特别的用处嘛。加10我就直接加10好了,加1就直接加1好了,不是本来就十分方便吗,反而这样更麻烦,因此没有加以重视。但是上面只是一个简单的例子从中来解释curry的概念,如果它的用途真的只是用来加法运算那却是是没什么用了。
以下几个例子来源于mostly-adequate-guide chapter04:Curring
const curry = require('lodash').curry;
const match = curry((what, s) => s.match(what));
const replace = curry((what, replacement, s) => s.replace(what, replacement));
const filter = curry((f, xs) => xs.filter(f));
const map = curry((f, xs) => xs.map(f));
策略性地把要操作的数据(String, Array)放到最后一个参数里。到使用它们的时候你就明白这样做的原因是什么了。
match(/r/g, 'hello world'); // [ 'r' ]
const hasLetterR = match(/r/g); // x => x.match(/r/g)
hasLetterR('hello world'); // [ 'r' ]
hasLetterR('just j and s and t etc'); // null
filter(hasLetterR, ['rock and roll', 'smooth jazz']); // ['rock and roll']
const removeStringsWithoutRs = filter(hasLetterR); // xs => xs.filter(x => x.match(/r/
g))
removeStringsWithoutRs(['rock and roll', 'smooth jazz', 'drum circle']); // ['rock and
roll', 'drum circle']
const noVowels = replace(/[aeiou]/ig); // (r,x) => x.replace(/[aeiou]/ig, r)
const censored = noVowels('*'); // x => x.replace(/[aeiou]/ig, '*')
censored('Chocolate Rain'); // 'Ch*c*l*t* R**n'
通过收集参数,传递小于函数预期个数的参数给调用函数,就能得到一个记住了这些参数的新函数。
这样通过不断地部分参数的传递得到新的能够通用的函数,就能将代码更好地复用。
成长有限,目前还是没能实际使用编写过函数式编程的代码,但也能确确实实地感受到它的价值了,也算是一种进步了。
讲讲curry的实现
lodash.js curry
var abc = function(a, b, c) {
return [a, b, c];
};
var curried = _.curry(abc);
curried(1)(2)(3);
// => [1, 2, 3]
curried(1, 2)(3);
// => [1, 2, 3]
curried(1, 2, 3);
// => [1, 2, 3]
curry使用
- 当我们传递的参数个数等于目标函数的预期个数的时候直接返回结果
- 当传递的参数小于预期函数的时候,返回一个新的函数,这个函数此时已经收集了之前传递进去的所有参数了,现在你只要将剩余的参数传入即可
实现的关键点
- 预期函数的个数,实际就是
function.length - 返回新的包含之前参数的函数。实际就是利用
Function.prototype.bind
主体功能实现:
function curry(targetfn) {
// 预期参数个数
var numOfArgs = targetfn.length;
return function curried() {
// 参数个数小于的话把之前传入的参数收集起来,再次返回curry化的函数
if (arguments.length < numOfArgs) {
return curried.bind(null, ...arguments);
// without ES6
// return Function.prototype.bind.apply(curried, [null].concat(Array.prototype.slice.call(arguments)));
} else {
return targetfn.apply(null, arguments);
}
}
}
这种方法利用的是闭包,将targetfn和numOfArgs私有化,变成内部变量
当传递的参数等于numOfArgs时候,调用targetfn
参考
谈谈函数式编程curry的更多相关文章
- restapi(7)- 谈谈函数式编程的思维模式和习惯
国庆前,参与了一个c# .net 项目,真正重新体验了一把搬砖感觉:在一个多月时间好像不加任何思考,不断敲键盘加代码.我想,这也许是行业内大部分中小型公司程序猿的真实写照:都是坐在电脑前的搬砖工人.不 ...
- js函数式编程curry与compose实现
//自行实现以下curry函数和compose //curry function curry(fn) { return function aa (...arg) { if (arg.length &g ...
- 函数式编程之柯里化(curry)
函数式编程curry的概念: 只传递给函数一部分参数来调用函数,然后返回一个函数去处理剩下的参数. var add = function(x) { return function(y) { retur ...
- laravel中closure和curry 科里化函数式编程
推荐值得的一看博客文档:谢谢作者 : https://my.oschina.net/zhmsong 函数式编程curry的概念: 只传递给函数一部分参数来调用函数,然后返回一个函数去处理剩下的参数. ...
- 翻译连载 | 附录 A:Transducing(上)-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇
原文地址:Functional-Light-JS 原文作者:Kyle Simpson-<You-Dont-Know-JS>作者 关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTM ...
- C#函数式编程
提起函数式编程,大家一定想到的是语法高度灵活和动态的LISP,Haskell这样古老的函数式语言,往近了说ruby,javascript,F#也是函数式编程的流行语言.然而自从.net支持了lambd ...
- Atitit 函数式编程与命令式编程的区别attilax总结 qbf
Atitit 函数式编程与命令式编程的区别attilax总结 qbf 1.1. 函数式程序就是一个表达式.命令式程序就是一个冯诺依曼机的指令序列. 命令式编程是面向计算机硬件的抽象,有变量(对应着存 ...
- JavaScript 与函数式编程
原文:https://bethallchurch.github.io/JavaScript-and-Functional-Programming/ 译文:http://www.zcfy.cc/arti ...
- C#函数式编程之由函数构建函数
在面向对象的编程中,如果我们需要复用其他的类,我们可以通过继承来实现.而在函数式编程中我们也可以采取不同的方式来复用这些函数.今天的教程将会讲述两种方式,其中一个就是组合,将多个函数组合成为一个函数, ...
随机推荐
- JS闭包(1)
1.首先看一段代码: var a = 1; function fn1(){ var b = 2; function fn2(){ console.log(a); console.log(b); } } ...
- 吴裕雄 Bootstrap 前端框架开发——Bootstrap 显示代码:同一行代码片段: span, div
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- 把链接生成二维码 二维码中间带有logo
在工程中引入三个文件jquery.qrcode.js.qrcode.js.utf.js.其中utf.js文件是防止链接中的参数出现中文乱码现象 jquery.qrcode.js文件 function ...
- leetcode209 Minimum Size Subarray Sum
""" Given an array of n positive integers and a positive integer s, find the minimal ...
- 吴裕雄--天生自然HADOOP操作实验学习笔记:安装zookeeper集群
实验目的 了解zookeeper的概念和原理 学会安装zookeeper集群并验证 掌握zookeeper命令使用 实验原理 1.Zookeeper介绍 ZooKeeper是一个分布式的,开放源码的分 ...
- 吴裕雄 Bootstrap 前端框架开发——Bootstrap 表格:表示信息变化的操作
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- 【剑指Offer面试编程题】题目1505:两个链表的第一个公共结点--九度OJ
题目描述: 输入两个链表,找出它们的第一个公共结点. 输入: 输入可能包含多个测试样例. 对于每个测试案例,输入的第一行为两个整数m和n(1<=m,n<=1000):代表将要输入的两个链表 ...
- English-Names
English-Names 1. 西方姓名的组成 2. 职业姓氏 3. 更多相关链接 中国的姓名,姓氏在前,名子在后.传统也有中间字(世代字).名子非常多.所谓百家姓,姓氏数量有限,约500个左右. ...
- codeforces 962 F Simple Cycles Edges
求简单环,即求点=边数的点双分量,加上判断点和边的模板即可 (简单环模板,区分与点双缩点) ; ], edgecnt, dfn[maxm], low[maxm], bcc_cnt, bccnum[ma ...
- Python 100 Days
Day 1 python的缺点 执行效率稍低,因此计算密集型任务可以由C/C++编写. 在开发时可以选择的框架太多(如Web框架就有100多个),有选择的地方就有错误. python解释器 官方的Py ...