时间:2021-05-28
最早期的curry函数有点多态的意味,就是根据函数参数在内部选用分支:
复制代码 代码如下:
//http://www.openlaszlo.org/pipermail/laszlo-user/2005-March/000350.html
// ★★On 8 Mar 2005, at 00:06, Steve Albin wrote:
function add(a, b) {
if (arguments.length < 1) {
return add;
} else if (arguments.length < 2) {
return function(c) { return a + c }
} else {
return a + b;
}
}
var myadd = add( 2 );
var total = myadd(3);
日本的一个先行者可能在未搞清arguments也能用Array的原生方法转换为数组的时候,用非常复杂的正则与eval搞出一个更接近现代currying意味的函数。
复制代码 代码如下:
function curry(fun) {
if (typeof fun != 'function') {
throw new Error("The argument must be a function.");
}
if (fun.arity == 0) {
throw new Error("The function must have more than one argument.");
}
var funText = fun.toString();
var args = /function .*\((.*)\)(.*)/.exec(funText)[1].split(', ');
var firstArg = args.shift();
var restArgs = args.join(', ');
var body = funText.replace(/function .*\(.*\) /, "");
var curriedText =
"function (" + firstArg + ") {" +
"return function (" + restArgs + ")" + body +
"}";
eval("var curried =" + curriedText);
return curried;
}
function curry(fun) { if (typeof fun != 'function') { throw new Error("The argument must be a function."); } if (fun.arity == 0) { throw new Error("The function must have more than one argument."); } var funText = fun.toString(); var args = /function .*\((.*)\)(.*)/.exec(funText)[1].split(', '); var firstArg = args.shift(); var restArgs = args.join(', '); var body = funText.replace(/function .*\(.*\) /, ""); var curriedText = "function (" + firstArg + ") {" + "return function (" + restArgs + ")" + body + "}"; eval("var curried =" + curriedText); return curried; } function sum(x, y) { return x + y; } function mean3(a, b, c) { return (a + b + c)/3; } var a = curry(sum)(10)(15) alert(a)//25 var b = curry(mean3)(10)(20, 30); alert(b)//20 var c = curry(curry(sum))(10)()(20); alert(c); var d = curry(curry(mean3)(10))(20)(30); alert(d); [Ctrl+A 全选 注:引入外部Js需再刷新一下页面才能执行]
接着是闭包的流行,与数组转换arguments的技术的发现,现代currying函数终于粉墨登场,就好像15~17世纪大航海时代的地理大发现,javascript的世界突然间开阔了许多。
复制代码 代码如下:
//一个简单的现代currying函数
function curry (fn, scope) {
var scope = scope || window;
var args = [];
for (var i=2, len = arguments.length; i < len; ++i) {
args.push(arguments[i]);
};
return function() {
fn.apply(scope, args);
};
}
一般的currying函数只有两重,执行情况如下,第一次执行参数不足返回内部函数,第二次执行才最终完成。不过针对这参数,我们还是可以做一些文章。看如下函数:
复制代码 代码如下:
function sum(){
var result=0;
for(var i=0, n=arguments.length; i<n; i++){
result += arguments[i];
}
return result;
}
alert(sum(1,2,3,4,5)); // 15
这就没有所谓的参数不足问题,传入一个参数,它也计算。但不传入参数呢?无错,区别在于有没有参数。我们可以让它不断执行自身,如果参数存在的情况下。最后在没有参数的情况下,一次过执行。换言之,前面的步骤是用于储存参数。
var sum2= curry(sum);
sum2= sum2(1)(2)(3)(4)(5);
sum2(); // 15
比起一般的currying函数,这有点难度。具体看注解:
复制代码 代码如下:
var curry= function(fn){//原函数的参数为函数
return function(args){//内部函数的参数为数组,由于立即执行,因此直接到第三重去
//args是相对于第三重内部函数可是全局变量
var self= arguments.callee;//把自身保存起来(就是那个数组为参数的第二重函数)
return function(){ //这才是第二次调用的函数
if(arguments.length){//如果还有要添加的参数
[].push.apply(args,arguments);//apply把当前传入的所有参数放进args中
return self(args);
}else{
return fn.apply(this,args);//apply的第二参数为数组
}
}
}([]);
};
function sum(){ var result=0; for(var i=0, n=arguments.length; i
function sum(){ var result=0; for(var i=0, n=arguments.length; i
复制代码 代码如下:
function curry(f) {
if (f.length == 0) return f;
function iterate(args) {
if (args.length <= f.length)
return f.apply(null, args);
return function () {
return iterate(args.concat(Array.prototype.slice.call(arguments)));
};
}
return iterate([]);
}
function curry(f) { if (f.length == 0) return f; function iterate(args) { if (args.length >= f.length) return f.apply(null, args); return function () { return iterate(args.concat(Array.prototype.slice.call(arguments))); }; } return iterate([]); } function mean3(a, b, c) { return (a + b + c) / 3; } var curriedMean3 = curry(mean3); alert(curriedMean3(1)(2, 3)); // => 2 alert(curriedMean3(1)(2)(3));//空括号无效 alert(curriedMean3()(1)()(2)()(3)); // => 2 alert(curriedMean3(1, 2)(3, 4)); // => 2 (第四个参数无效) [Ctrl+A 全选 注:引入外部Js需再刷新一下页面才能执行]
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
几个星期前,我发了一条微博说我喜欢返回函数的函数。很快就出现了几个回复,基本是都是….什么东东?!对于一个程序员来说,理解返回函数的函数是一个非常重要的技能,使
柯里化(Currying)是把接收多个参数的原函数变换成接受一个单一参数(原来函数的第一个参数的函数)并返回一个新的函数,新的函数能够接受余下的参数,并返回和原
前言C语言返回字符串函数共有四种方式,分别如下:使用堆空间,返回申请的堆地址,注意释放函数参数传递指针,返回该指针返回函数内定义的静态变量(共享)返回全局变量下
在C++中,函数的形参可以是指向函数的指针,函数也可以返回函数的指针。例如:int(*ff(int))(int*,int);表示:ff(int)是一个函数,带有
概述匿名函数,顾名思义即没有名称的函数,和def定义的函数的最大区别在于匿名函数创建后返回函数本身(即匿名函数不需要return来返回值),表达式本身结果就是返