在javascript中对具有n个参数的函数进行curry

在javascript中对具有n个参数的函数进行curry,javascript,functional-programming,currying,Javascript,Functional Programming,Currying,如果f::a,b->c,我们可以定义curryf如下: 货币:a,b->c->a->b->c const curry = f => a => b => f(a, b); const sum = curry((num1, num2) => num1 + num2); console.log(sum(2)(3)); //5 我们如何实现一个带有n个参数的函数的通用curry函数?警告:我没有函数背景,所以我的术语可能有点离谱 如果curry的意思是创建一个新函数,该函数将调

如果f::a,b->c,我们可以定义curryf如下:

货币:a,b->c->a->b->c

const curry = f => a => b => f(a, b);
const sum = curry((num1, num2) => num1 + num2);
console.log(sum(2)(3)); //5

我们如何实现一个带有n个参数的函数的通用curry函数?

警告:我没有函数背景,所以我的术语可能有点离谱

如果curry的意思是创建一个新函数,该函数将调用原始函数并预先填充一些参数,那么ES5及更早版本中的一般解决方案如下所示,请参见注释:

//将函数添加到函数原型 Object.definePropertyFunction.prototype,curry{ 值:函数{ //还记得最初的函数吗 var f=这个; //还记得那些陈词滥调吗 var args=Array.prototype.slice.callarguments; //返回一个新函数来完成此工作 返回函数{ //已调用新函数:使用 //curried参数后跟在中接收到的任何参数 //此调用,传递“this”的当前值` 返回f.applythis,args.concatArray.prototype.slice.callarguments; }; } }; //用法: 函数fooa、b、c{ 控制台。loga、b、c; } var f=foo.curry1,2;
f3 如果我理解正确,我认为这是使用ES6的方法:

const curry=f=>{ const nargs=f.长度; 常量变量=[]; 常量curried=…args=>vargs.push…args>=nargs ?f…vargs.0,nargs :咖喱; 返回咖喱; }; 常数fn2=currya,b=>a+b; 常数fn3=currya,b,c=>a*b+c; 常数fn4=currya,b,c,d=>Math.powa,b*c+d; console.logfn212;//1 + 2 console.logfn3234;//2 * 3 + 4 console.logfn421,34;//2^1*3+4ES6/2015

const curry=fn=>函数curriedcargs{ return cargs.length>=fn.length?fn.applythis,cargs:…args=>咖喱[…cargs,…args] }[]; 常数arg2=currya,b=>a+b; 常数arg3=currya,b,c=>a*b+c; 常量arg4=currya,b,c,d=>Math.powa,b*c+d; console.logarg212;//1 + 2 console.logarg3234;//2 * 3 + 4
console.logarg421,34;//2^1*3+4有一种简单的方法可以用无限参数来实现求和函数

const add=a=>{ const next=b=>adda+b; next.valueOf==>a 下一步返回; }; 常数1=add1; console.logone.valueOf; 常数2=1+1; 控制台2; 常数四=二+二; 控制台logfour 常数六=加四二; console.logsix.valueOf; 常数11=6 41;
console.logeleven.valueOf 以下是一个受Juan Sebastián Gaitán解决方案启发的解决方案,我刚刚将其扩展到以下情况:

add1,22,31,2,3,4.valueOf; 添加1,2,3,4.0个值; 加上12345.0元; 常量add=a,…rest=>{ a+=rest.reducetotal,val=>{ 返回total+val; }, 0; 常量next=…b=>adda+b.reducetotal,val=>{ 返回total+val; }, 0; next.valueOf==>a; //console.log'a',a',next:',next',rest:',…rest; 下一步返回; }; console.logadd1,22,31,2,3,4.valueOf//18 console.logadd1,2,3,4.valueOf//10
console.logadd12345.valueOf//你是说f::a,b->c->a->b->c吗?@Patrick Roberts Yes我喜欢这些挑战。我应该写一个库或者一些带有一些实用程序的东西,也许人们会觉得它值得使用。我已经接受了,并且投了赞成票。接受的选项在哪里?我已经点击了你答案左侧的向上箭头。抱歉,遗漏了a,直到我添加了片段才注意到。我想我们用不同的方式解释了这个问题,我想我们会看到谁的解释是正确的:P@PatrickRoberts:真的!:-他们都是他们回答问题的好答案,我们来看看谁回答了OP的问题。@T.J.Crowder谢谢你的评论。为了确保我理解,如果你要这样做,就让f=foo.curry;f123;这会做同样的事情吗?@PatrickRoberts:Gah,我是,并且把enumerable误读为可配置的。太好了,这让事情简单多了。@PatrickRoberts:是的,看到了,很酷的东西!如果可以的话,我会再次投票。但是保持长度不可写,并为生成的函数烘焙正确的值不是更好吗?@t.J.Crowder您提到了几种方法,但我认为最可行的函数构造函数比配置.length属性更可取。我很确定它首先是可配置的,允许像这样的小场景在有意义的时候改变它。@PatrickRoberts:哦,你绝对不想要函数构造函数。我在想,在生成curried函数之后,您应该执行Object.definePropertycurry,length{value:properteLengthHere}。只是保持它不可写,但仍然使用它是可配置的事实,实际上,添加可配置:对我的例子来说是真实的-可能还需要支付。