JS中的 偏函数 和 柯里化
栏目: JavaScript · 发布时间: 5年前
内容简介:在计算机科学中,偏函数应用 是指将一些参数固定到一个函数,产生另一个较小的函数的过程。举个例子:基于这个函数,我们利用
什么是偏函数
在计算机科学中,偏函数应用 是指将一些参数固定到一个函数,产生另一个较小的函数的过程。
举个例子:
// 我们创建了一个做 乘法运算 的函数 function mult(a, b) { return a * b; };复制代码
基于这个函数,我们利用 bind
创造一个新的函数 double
:
let double = mult.bind(null, 2); console.log( double(3) ); // mult(2, 3) = 6; console.log( double(4) ); // mult(2, 4) = 8; console.log( double(5) ); // mult(2, 5) = 10; 复制代码
mult.bind(null, 2)
创造了一个新函数 double
,传递调用到 mult
函数,以 null
为 context
, 2
为第一个参数。其他参数等待传入。
这就是 偏函数应用 —— 我们创造了一个新函数,同时将部分参数替换成特定值。
什么时候使用偏函数
刚刚我们基于 mult
创建了一个新的函数 double
,这里我们再创建一个新的函数 triple
:
let triple = mult.bind(null, 3); console.log( triple(3) ); // mult(3, 3) = 9; console.log( triple(4) ); // mult(3, 4) = 12; console.log( triple(5) ); // mult(3, 5) = 15;复制代码
使用 偏函数
,我们能够从中受益的是:我们创建了一个独立的非匿名函数( double
, triple
)。我们可以使用它,而不需要每次都传入第一个参数,因为 bind
帮我们搞定了。
在其他的场景中,当我们有一个非常通用的函数,并且想要方便地获取它的特定变体,偏函数也是非常有用。
举个例子,我们拥有函数 post(signature, api, data)
。在调用请求方法的时候有着相同的用户签名,这里我们想要使用它的偏函数变体: post(api, data)
,表明该请求发送自同一用户签名。
什么是柯里化
有时候人们会把 偏函数应用 和另外一个名为 柯里化 的东西混淆,但那的确是另外一个和函数有关的有趣技术。
在 函数式编程语言 和 其他许多语言 中,柯里化(currying)提供了一种自动管理参数如何传递给函数和异常的方法。
简单来说, currying
是一项将一个调用形式为 f(a, b, c)
的函数转化为调用形式 f(a)(b)(c)
的技术。
举个例子:
function currying(fn) { return function(a) { return function(b) { return fn(a, b); }; }; } // 用法 function sum(a + b) { return a + b; } let carriedSum = currying(sum); console.log( carriedSum(1)(2) ); // 3复制代码
从上面的例子可以看到, carrying
的实现就是一系列的封装。
-
currying(fn)
的结果就是一层封装function(a)
。 -
当它被调用,就像
carriedSum(1)
这样,它的参数被保存到 词法环境 中,然后返回一层新的封装function(b)
。 -
然后
carriedSum(1)(2)
调用function(b)
,传入参数2
,它将调用传递给初始的多参数函数sum
。
结合之前的 偏函数
知识,我们可以看到, sum
函数在 柯里化
之后,逐个传递参数的时候返回的那一层封装:其实就是 sum
函数 的 偏函数变体
。
这可能也是大家容易将这个两个概念搞混的原因之一吧。
高级柯里化
高级的柯里化同时允许 函数正常调用 和 获取偏函数 。
我们可以实现一下 高级的柯里化:
function currying(fn) { return function curried(...args) { if(args.length>=fn.length) { // 传入的实参长度 >= 初始函数形参长度 的时候,则直接执行初始函数 return fn.apply(this, args); } else { // 否则 得到一个 偏函数,递归carried方法,直到获得所有参数后,直接执行 return function(...args2) { return curried.apply(this, args.concat(args2)); } } } } function sum(a, b, c) { return a + b + c; } let curriedSum = currying(sum); // 常规调用 console.log( curriedSum(1, 2, 3) ); // 6 // 得到 curriedSum(1)的偏函数,然后用另外两个参数调用它 console.log( curriedSum(1)(2, 3) ); // 6 // 完全柯里化调用 console.log( curriedSum(1)(2)(3) ); // 6复制代码
柯里化的目的是什么?
从上面的 高级柯里化 实现的例子中可以发现:
-
sum
函数 在 柯里化 之后对于使用并没有任何影响,仍然可以被正常调用。 - 在很多情况下,我们可以更方便的生成 偏函数 变体,可以更灵活的被我们使用。
总得来说, 柯里化的目的 就是在不影响 初始函数 的调用形式的情况下,更方便的让我们获得初始函数的 偏函数 变体。
最后,欢迎各位小伙伴留言,相互讨论。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Python 拓展之特殊函数(lambda 函数,map 函数,filter 函数,reduce 函数)
- Python 函数调用&定义函数&函数参数
- python基础教程:函数,函数,函数,重要的事说三遍
- C++函数中那些不可以被声明为虚函数的函数
- 017.Python函数匿名函数
- 纯函数:函数式编程入门
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Introduction to Computation and Programming Using Python
John V. Guttag / The MIT Press / 2013-7 / USD 25.00
This book introduces students with little or no prior programming experience to the art of computational problem solving using Python and various Python libraries, including PyLab. It provides student......一起来看看 《Introduction to Computation and Programming Using Python》 这本书的介绍吧!