如何在未知数量的参数上curry一个函数
How to curry a function across an unknown number of parameters
假设我有一个函数叫multiplyDivide
如果我叫multiplyDivide(2)(3)(4)(6)
,它就等于2 * 3 / 4 * 6
。
更新:有没有可能写出这样一个函数如果我事先不知道要取多少参数呢?例如,我可以输入multiplyDivide(1)(2)
或multiplyDivide(1)(2)(3)(4)...(n-1)(n)
这是可能的,但你需要定义终止条件,因为这个问题本质上和写递归函数是一样的。函数需要一种方法来判断它应该返回一个函数还是一个值。
如何表示需要值取决于你自己。一种方法是检查是否传递了参数:
// Using add instead of multiplyDivide to simplify example:
function add (num) {
function adder (n) {
if (n !== undefined) {
num += n;
return adder;
}
else { // terminate
return num;
}
}
return adder;
}
现在你可以这样做:
var sum = add(1)(2)(3)(4)();
否则它将返回一个函数,你可以一直调用:
var x = add(1)(2)(3)(4);
x = x(5)(6)(7);
x = x(8)(9)(10);
var sum = x();
因为在js函数是对象,你也可以实现值getter作为一个静态方法。它不会是纯粹的功能,但使"API"更显式,更容易阅读:
function add (num) {
function adder (n) {
num += n;
return adder;
}
adder.value = function(){
return num
};
return adder;
}
这将允许你做:
var sum = add(1)(2)(3)(4).value();
您甚至可以通过重写内置的.valueOf()
和.toString()
方法来获得花式:
function add (num) {
function adder (n) {
num += n;
return adder;
}
adder.valueOf = function(){
return num
};
adder.toString = function(){
return '' + num
};
return adder;
}
这将允许你做:
var sum = add(1)(2)(3)(4) + 5; // results in 15
var txt = add(1)(2)(3)(4) + "hello"; // results in "10hello"
这里的关键是需要一种方法来告诉函数停止返回函数。
使用函数式方法,您可以创建一个为另一个函数"处理"参数的函数。您需要一种方法来告诉函数返回值,因此在本例中,调用函数而不传递任何参数将返回结果:
function curry(fn, ...values) {
return (...next) => (next.length) ? curry(fn, ...values, ...next) : fn(...values);
}
这个函数最酷的地方是你可以传递多个参数和/或继续调用函数(1)(2, 3, 4)(5)
。
这里有几个例子:
function curry(fn, ...values) {
return (...next) => (next.length) ? curry(fn, ...values, ...next) : fn(...values);
}
function multiplyDivide(...args) {
return args.reduce((total, next, i) => (i % 2) ? (total / next) : (total * next), args.shift());
}
let x = curry(multiplyDivide)(2)(3, 4)(6)();
console.log(x);
let y = curry(multiplyDivide)(5, 4, 2)(3);
y = y(3, 5)(1)();
console.log(y);
当然,这个例子确实暗示了只要简单地重载multiplyDivide
函数,并在你准备好时将你的值传递给它:
function multiplyDivide(...args) {
return args.reduce((total, next, i) => (i % 2) ? (total / next) : (total * next), args.shift());
}
const values = [5, 4, 2, 3, 3];
values.push(5, 1);
console.log(multiplyDivide(...values));
你的意思是这样吗?
var multiplyDivide = function(first){
return function(second){
return function(third){
return function(forth){
return first * second / third * forth;
}
}
}
}
//should be 6
console.log(multiplyDivide(2)(4)(4)(3));
这其实是一个非常好的问题…
柯里化是函数式编程语言中最基本的方面之一,你可以在其中传递和返回函数。JS在某种程度上是一种函数式编程语言,应该能够执行此操作。
所以就像你的问题一样,人们可能会因为这样或那样的原因想要curry一个无限多参数的函数。
让你的函数为
function multiplyDivide (n,m,o,p){
return n * m / o * p;
}
那么实现curry
实用函数以获取任意给定函数的柯里化版本的方法如下:
var curry = f => f.length ? (...a) => curry(f.bind(f,...a)) : f(),
让我们看看它的作用
function multiplyDivide (n,m,o,p){
return n * m / o * p;
}
var curry = f => f.length ? (...a) => curry(f.bind(f,...a)) : f(),
f = curry(multiplyDivide);
res1 = f(4,5,2,10),
res2 = f(4)(5,2,10),
res3 = f(4)(5)(2,10),
res4 = f(4)(5)(2)(10),
res5 = f(4,5)(2,10),
res6 = f(4,5)(2)(10),
res7 = f(4,5,2)(10),
res8 = f(4,5)(2,10);
console.log(res1,res2,res3,res4,res5,res6,res7,res8);
可能有更简单的方法,但这是我能想到的
function addValues(a, b) {
if(b!=undefined)
return a + b;
return function(b) {
return a + b;
}
}
let output1 = addValues(2)(4); // 6
let output2 = addValues(2,1); // 3
console.log(output1);
console.log(output2)
function multiply(a) {
return function(b) {
return b ? multiply(a*b) : a;
}
}
console.log(multiply(2)());
console.log(multiply(2)(3)());
console.log(multiply(2)(3)(4)());
console.log(multiply(2)(3)(4)(5)());
function add() {
let args = [...arguments];
function addAll(){
let args1 = [...arguments];
return add(...args, ...args1);
}
let total = args.reduce((total, value) => total+value);
addAll.value = total;
return addAll;
}
console.log(add(2)(3)(4).value);
console.log(add(2)(3).value);
- 创建一个类似链接的按钮,并通过Javascript函数打开一个新的弹出窗口
- 我可以在json对象中添加一个函数吗
- Javascript使函数一个接一个地执行
- 是JavaScript中的函数一个对象
- 两个几乎相等的jQuery函数;一个适用于IE,一个不适用于IE
- 两个Javascript函数一个window.onload=Custom.init;和一个window.onload=f
- 使javascript加载函数一个接一个地执行
- 如何通过两个嵌套的匿名函数(一个带有超时的事件处理程序)传递变量
- 为什么我不能让两个jQuery函数一个在另一个里面呢?
- 给函数一个变量名,而不是它的值
- 如何使用嵌入函数(一个滚动页由Pete - peachananr)
- 是否有可能给JavaScript函数一个类型/类?
- 确保两个函数一个接一个地执行,其中第一个函数内部有一个异步调用
- 两个不同的ajax函数一个接一个调用返回相同的值
- jQuery第一次更改函数一个工作
- 给这个函数一个id
- 如何给回调函数一个值一个变量在特定时刻
- 使用回调使两个函数一个接一个地运行
- 两个函数(一个用php)是否可以用“;onclick”;
- 两个几乎相同的函数.一个函数用Queue进行排队.Jquery效果在queued函数上不起作用.为什么