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使用

  • 当我们传递的参数个数等于目标函数的预期个数的时候直接返回结果
  • 当传递的参数小于预期函数的时候,返回一个新的函数,这个函数此时已经收集了之前传递进去的所有参数了,现在你只要将剩余的参数传入即可

实现的关键点

  1. 预期函数的个数,实际就是function.length
  2. 返回新的包含之前参数的函数。实际就是利用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);
}
}
}

这种方法利用的是闭包,将targetfnnumOfArgs私有化,变成内部变量

当传递的参数等于numOfArgs时候,调用targetfn

参考

谈谈函数式编程curry的更多相关文章

  1. restapi(7)- 谈谈函数式编程的思维模式和习惯

    国庆前,参与了一个c# .net 项目,真正重新体验了一把搬砖感觉:在一个多月时间好像不加任何思考,不断敲键盘加代码.我想,这也许是行业内大部分中小型公司程序猿的真实写照:都是坐在电脑前的搬砖工人.不 ...

  2. js函数式编程curry与compose实现

    //自行实现以下curry函数和compose //curry function curry(fn) { return function aa (...arg) { if (arg.length &g ...

  3. 函数式编程之柯里化(curry)

    函数式编程curry的概念: 只传递给函数一部分参数来调用函数,然后返回一个函数去处理剩下的参数. var add = function(x) { return function(y) { retur ...

  4. laravel中closure和curry 科里化函数式编程

    推荐值得的一看博客文档:谢谢作者  : https://my.oschina.net/zhmsong 函数式编程curry的概念: 只传递给函数一部分参数来调用函数,然后返回一个函数去处理剩下的参数. ...

  5. 翻译连载 | 附录 A:Transducing(上)-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇

    原文地址:Functional-Light-JS 原文作者:Kyle Simpson-<You-Dont-Know-JS>作者 关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTM ...

  6. C#函数式编程

    提起函数式编程,大家一定想到的是语法高度灵活和动态的LISP,Haskell这样古老的函数式语言,往近了说ruby,javascript,F#也是函数式编程的流行语言.然而自从.net支持了lambd ...

  7. Atitit 函数式编程与命令式编程的区别attilax总结  qbf

    Atitit 函数式编程与命令式编程的区别attilax总结  qbf 1.1. 函数式程序就是一个表达式.命令式程序就是一个冯诺依曼机的指令序列. 命令式编程是面向计算机硬件的抽象,有变量(对应着存 ...

  8. JavaScript 与函数式编程

    原文:https://bethallchurch.github.io/JavaScript-and-Functional-Programming/ 译文:http://www.zcfy.cc/arti ...

  9. C#函数式编程之由函数构建函数

    在面向对象的编程中,如果我们需要复用其他的类,我们可以通过继承来实现.而在函数式编程中我们也可以采取不同的方式来复用这些函数.今天的教程将会讲述两种方式,其中一个就是组合,将多个函数组合成为一个函数, ...

随机推荐

  1. SpringMvc 返回json的三种方式

    参考:https://blog.csdn.net/fupengyao/article/details/62220886

  2. js 原生url编码

    参考:http://www.runoob.com/jsref/jsref-decodeuricomponent.html

  3. Python实现简单中文词频统计示例

    简单统计一个小说中哪些个汉字出现的频率最高: import codecs import matplotlib.pyplot as plt from pylab import mpl mpl.rcPar ...

  4. 学习笔记(14)- SQuAD的数据格式

    BERT模型完成问答任务的时候,需要数据格式为SQuAD形式. 有2个版本,1.1和2.0

  5. Linux软Raid--mdadm命令

    mdadm:为软RAID提供管理界面,RAID设备可命名为/dev/md0./dev/md1./dev/md2./dev/md3等 命令的语法格式:mdadm[mode] <raiddevice ...

  6. [原]JointJS流程图

    最近项目上需要用流程图来做问题定界分析,之前有同事用jsPlumb做过,但是阅读代码后觉得比较麻烦,所以自己又找了一圈,找到一个叫Dagre-D3的开源类库,画出来的效果如下图,Dagre-D3最大的 ...

  7. nodejs中this详解

    最近在用Nodejs进行APP运维服务管理系统开发时发现,nodejs中的this经常会变,查了下资料后发现this在不同的代码位置中代表不同的涵义,在实际运用过程中可以用var self = thi ...

  8. uniGUI读取文本文件(08)

    为了测试没有数据库下的简单入门例子 procedure TMainForm.UniButton2Click(Sender: TObject); // 读取 文本 var aStringlist: Ts ...

  9. [PHP] PHP7已经删除了preg_replace的e修饰符

    官网提示是这样的,对/e修饰符的支持已删除.请改用preg_replace_callback()原因是/e 修正符使 preg_replace() 将 replacement 参数当作 PHP 代码( ...

  10. Pytorch model saving and loading 模型保存和读取

    It is really useful to save and reload the model and its parameters during or after training in deep ...