前端开发者进阶之函数柯里化Currying
穆乙:http://www.cnblogs.com/pigtail/p/3447660.html
在计算机科学中,柯里化(英语:Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。这个技术由 Christopher Strachey 以逻辑学家哈斯凯尔·加里命名的,尽管它是 Moses Schönfinkel 和 Gottlob Frege 发明的。
这是来自维基百科的名词解释。顾名思义,柯里化其实本身是固定一个可以预期的参数,并返回一个特定的函数,处理批特定的需求。这增加了函数的适用性,但同时也降低了函数的适用范围。
看一下通用实现:
function currying(fn) {
var slice = Array.prototype.slice,
__args = slice.call(arguments, 1);
return function () {
var __inargs = slice.call(arguments);
return fn.apply(null, __args.concat(__inargs));
};
}
柯里化的实用性体现在很多方面:
1 提高适用性。
【通用函数】解决了兼容性问题,但同时也会再来,使用的不便利性,不同的应用场景往,要传递很多参数,以达到解决特定问题的目的。有时候应用中,同一种规则可能会反复使用,这就可能会造成代码的重复性。
看下面一个例子:
function square(i) {
return i * i;
} function dubble(i) {
return i *= 2;
} function map(handeler, list) {
return list.map(handeler);
} // 数组的每一项平方
map(square, [1, 2, 3, 4, 5]);
map(square, [6, 7, 8, 9, 10]);
map(square, [10, 20, 30, 40, 50]);
// ...... // 数组的每一项加倍
map(dubble, [1, 2, 3, 4, 5]);
map(dubble, [6, 7, 8, 9, 10]);
map(dubble, [10, 20, 30, 40, 50]);
例子中,创建了一个map通用函数,用于适应不同的应用场景。显然,通用性不用怀疑。同时,例子中重复传入了相同的处理函数:square和dubble。
应用中这种可能会更多。当然,通用性的增强必然带来适用性的减弱。但是,我们依然可以在中间找到一种平衡。
看下面,我们利用柯里化改造一下:
function square(i) {
return i * i;
} function dubble(i) {
return i *= 2;
} function map(handeler, list) {
return list.map(handeler);
} var mapSQ = currying(map, square);
mapSQ([1, 2, 3, 4, 5]);
mapSQ([6, 7, 8, 9, 10]);
mapSQ([10, 20, 30, 40, 50]);
// ...... var mapDB = currying(map, dubble);
mapDB([1, 2, 3, 4, 5]);
mapDB([6, 7, 8, 9, 10]);
mapDB([10, 20, 30, 40, 50]);
// ......
我们缩小了函数的适用范围,但同时提高函数的适性。当然,也有扩展函数适用范围的方法--反柯里化,留到下一篇再讨论。
由此,可知柯里化不仅仅是提高了代码的合理性,更重的它突出一种思想---降低适用范围,提高适用性。
下面再看一个例子,一个应用范围更广泛更熟悉的例子:
function Ajax() {
this.xhr = new XMLHttpRequest();
} Ajax.prototype.open = function(type, url, data, callback) {
this.onload = function() {
callback(this.xhr.responseText, this.xhr.status, this.xhr);
} this.xhr.open(type, url, data.async);
this.xhr.send(data.paras);
} 'get post'.split(' ').forEach(function(mt) {
Ajax.prototype[mt] = currying(Ajax.prototype.open, mt);
}); var xhr = new Ajax();
xhr.get('/articles/list.php', {},
function(datas) {
// done(datas)
}); var xhr1 = new Ajax();
xhr1.post('/articles/add.php', {},
function(datas) {
// done(datas)
});
2 延迟执行。
柯里化的另一个应用场景是延迟执行。不断的柯里化,累积传入的参数,最后执行。
看下面:
var add = function() {
var _this = this,
_args = arguments
return function() {
if (!arguments.length) {
var sum = 0;
for (var i = 0,
c; c = _args[i++];) sum += c
return sum
} else {
Array.prototype.push.apply(_args, arguments) return arguments.callee
}
}
}
add(1)(2)(3)(4)();//
通用的写法:
var curry = function(fn) {
var _args = []
return function cb() {
if (arguments.length == 0) {
return fn.apply(this, _args)
}
Array.prototype.push.apply(_args, arguments);
return cb;
}
}
上面累加的例子,可以实验一下怎么写?
3 固定易变因素。
柯里化特性决定了它这应用场景。提前把易变因素,传参固定下来,生成一个更明确的应用函数。最典型的代表应用,是bind函数用以固定this这个易变对象。
Function.prototype.bind = function(context) {
var _this = this,
_args = Array.prototype.slice.call(arguments, 1);
return function() {
return _this.apply(context, _args.concat(Array.prototype.slice.call(arguments)))
}
}
参考:
http://sombie.diandian.com/post/2013-06-28/40050585369
http://book.2cto.com/201211/9320.html
http://zh.wikipedia.org/wiki/Currying
http://www.ibm.com/developerworks/cn/web/1006_qiujt_jsfunctional/
前端开发者进阶之函数柯里化Currying的更多相关文章
- 函数柯里化(Currying)示例
”函数柯里化”是指将多变量函数拆解为单变量的多个函数的依次调用, 可以从高元函数动态地生成批量的低元的函数.可以看成一个强大的函数工厂,结合函数式编程,可以叠加出很BT的能力.下面给出了两个示例,说明 ...
- Swift函数柯里化(Currying)简谈
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 下面简单说说Swift语言中的函数柯里化.简单的说就是把接收多 ...
- 偏函数应用(Partial Application)和函数柯里化(Currying)
偏函数应用指的是固化函数的一个或一些参数,从而产生一个新的函数.比如我们有一个记录日志的函数: 1: def log(level, message): 2: print level + ": ...
- 应用js函数柯里化currying 与ajax 局部刷新dom
直接上代码吧 最近读javascript核心概念及实践的代码 感觉很有用 备忘. <div id="request"></div> <script t ...
- 深入理解javascript函数进阶系列第二篇——函数柯里化
前面的话 函数柯里化currying的概念最早由俄国数学家Moses Schönfinkel发明,而后由著名的数理逻辑学家Haskell Curry将其丰富和发展,currying由此得名.本文将详细 ...
- Javascript函数柯里化(curry)
函数柯里化currying,是函数式编程非常重要的一个标志.它的实现需要满足以下条件,首先就是函数可以作为参数进行传递,然后就是函数可以作为返回值return出去.我们依靠这个特性编写很多优雅酷炫的代 ...
- JS中的柯里化(currying)
何为Curry化/柯里化? curry化来源与数学家 Haskell Curry的名字 (编程语言 Haskell也是以他的名字命名). 柯里化通常也称部分求值,其含义是给函数分步传递参数,每次传递参 ...
- 前端开发者进阶之函数反柯里化unCurrying
函数柯里化,是固定部分参数,返回一个接受剩余参数的函数,也称为部分计算函数,目的是为了缩小适用范围,创建一个针对性更强的函数. 那么反柯里化函数,从字面讲,意义和用法跟函数柯里化相比正好相反,扩大适用 ...
- 前端进击的巨人(五):学会函数柯里化(curry)
柯里化(Curring, 以逻辑学家Haskell Curry命名) 写在开头 柯里化理解的基础来源于我们前几篇文章构建的知识,如果还未能掌握闭包,建议回阅前文. 代码例子会用到 apply/call ...
随机推荐
- Xamarin Error cannot find ‘aapt.exe’
Problem: solution: A workaround is to copy your files to the old directory. Just copy the aapt ...
- JavaScript获取客户端计算机硬件及系统等信息的方法
JavaScript获取客户端计算机硬件及系统等信息的方法 JavaScript 获取客户端计算机硬件及系统信息 通过WMI来实现获取客户端计算机硬件及系统信息: function getSysInf ...
- Qt 之 饼图
Qt 库由许多模块组成,其中的 Qt Charts,包含了一系列图表组件. 1 饼图 (pie chart) 1.1 Charts 模块 .pro 中添加如下语句: QT += charts 头文 ...
- springboot Serving Web Content with Spring MVC
Serving Web Content with Spring MVC This guide walks you through the process of creating a "hel ...
- 洛谷P1280 尼克的任务[DP]
题目描述 尼克每天上班之前都连接上英特网,接收他的上司发来的邮件,这些邮件包含了尼克主管的部门当天要完成的全部任务,每个任务由一个开始时刻与一个持续时间构成. 尼克的一个工作日为N分钟,从第一分钟开始 ...
- SQL高级查询:嵌套和分页
1.嵌套子查询 --查询最近一次oop考试没有参加考试的学生 select StudentName from Student where StudentNo not in( select Studen ...
- Java的泛型反射
If the superclass is a parameterized type, the {@code Type} * object returned must accurately reflec ...
- LoadLibrary加载动态库失败的解决办法
from:http://blog.sina.com.cn/s/blog_62ad1b8101017qub.html 若DLL不在调用方的同一目录下,可以用LoadLibrary(L"DLL绝 ...
- Error: Could not find the required version of the Java(TM) 2 Runtime Environment in'(null)'.
今天拿到一台新机器,搭一下开发环境,安装个JDK是个很基本的事情,从Orale的网站上下了个安装,但是一直出下面的错: 我信了你的邪,Google了一圈,有人说是可能文件下载有问题,重新下载安装就可以 ...
- CSS强制性换行
一般情况下,元素拥有默认的white-space:normal(自动换行,PS:不 换行是white-space:nowrap),当录入的文字超过定义的宽度后会自动换行,但当录入的数据是一堆没有空格的 ...