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. python3升级pip报错ImportError: cannot import name 'main'

    把系统的python版本从默认的2切换到3后,使用pip3安装依赖报错,如下: Traceback (most recent call last): File , in <module> ...

  2. Duilib 修改程序exe、在任务栏以及任务管理器上的图标

    参考:https://blog.csdn.net/Rongbo_J/article/details/47379997       https://www.cnblogs.com/happinessda ...

  3. IIS 应用程序池回收(代码实现)

    回收 public void StartStopRecycleApp(string appName = "项目DLL名称", string method = "Recyc ...

  4. Spring_MVC 21问

    1.什么是Spring MVC ?简单介绍下你对springMVC的理解? Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把Model,View,C ...

  5. [GWCTF 2019]mypassword

    这道题(不只这道题以后也一定)要注意控制台中的信息,给出了login.js代码,会把当前用户的用户名和密码填入表单 注册个账号,登录之后给提示不是注入题 浏览一下网站功能,feedback页面可以提交 ...

  6. Python 基础之import导包

    首先需要将import内容建立一个大概如下层级的包: 以黑色框为第一级,蓝色框为第二级,棕色框为第三级,红色框为第四级 一.import 引入初识 首先在module.py写入代码如下: xboy = ...

  7. linux 从一台服务器向另台服务器复制文件

    使用scp命令: sudo scp -P 2222 username@192.168.0.200:/home/db/db_data.sql.gz /home/db/db_data.sql.gz scp ...

  8. 十五 链表与递归,leetCode203题

    两种方式: package com.lt.datastructure.LinkedList; /** * leetCode 203题 * /** * Definition for singly-lin ...

  9. java SHA1加密算法

    package com.cn.test.rsa; import java.security.MessageDigest; import java.security.NoSuchAlgorithmExc ...

  10. 【Python数组及其基础操作】【numpy ndarray】

    一.创建数组 在python中创建数组最简单的办法就是使用array函数.它接受一切序列型的对象,然后产生一个含有传入数据的numpy数组.其中,嵌套序列(比如由一组等长列表组成的列表)会被转换为一个 ...