如何使用结果为 javascript 的回调函数实现无限柯里化总和值?
How to implement infinite currying sum values with a callback function with result in javascript?
我有一个测试,我需要在这种情况下实现一个名为 sum 的高阶函数,它满足以下要求:
sum(result => {console.log("-> ", result)});// -> prints: -> 0
sum(1)(result => {console.log("-> ", result)});// -> prints: -> 1
sum(1)(2)(result => {console.log("-> ", result)});// -> prints: -> 3
sum(1)(2)(4)(result => {console.log("-> ", result)});// -> prints: -> 7
我做了一个函数,以便通过递归获得无限柯里化,但我对回调函数有点迷茫。
let sum = a => !a ? 0 : b => b ? sum(a+b) : a
console.log(sum()) -> 0
console.log(sum(1)()) -> 1
console.log(sum(1)(2)()) -> 3
console.log(sum(1)(2)(4)()) -> 7
使用闭包来累加总和。当内部函数检测到参数是一个函数时,它将调用带有总和的回调。否则它会 return 自己调整和后:
function sum(arg) {
let total = 0;
function inner(arg) {
if (typeof arg === "function") {
arg(total);
} else {
total += arg;
return inner;
}
}
return inner(arg);
}
sum(result => {console.log("-> ", result)});// -> prints: -> 0
sum(1)(result => {console.log("-> ", result)});// -> prints: -> 1
sum(1)(2)(result => {console.log("-> ", result)});// -> prints: -> 3
sum(1)(2)(4)(result => {console.log("-> ", result)});// -> prints: -> 7
如果函数不打算保持状态,则可以使用 this
参数传递总数:
"use strict";
function sum(arg) {
function inner(arg) {
if (typeof arg === "function") {
arg(+this);
} else {
return inner.bind(this + arg);
}
}
return inner.call(0, arg);
}
sum(result => {console.log("-> ", result)});// -> prints: -> 0
sum(1)(result => {console.log("-> ", result)});// -> prints: -> 1
sum(1)(2)(result => {console.log("-> ", result)});// -> prints: -> 3
sum(1)(2)(4)(result => {console.log("-> ", result)});// -> prints: -> 7
const foo = sum(0);
foo(100)(console.log); // 100
foo(1)(console.log); // 1
此处建议使用严格模式,但在草率模式下也可以。在这种情况下,this
参数会再次装箱和拆箱。
为简单起见,您可以有一个接受两个参数的辅助函数。第一个参数是一个数字。第二个参数是一个数字或函数,根据类型它会做不同的事情:
- 当它是一个函数时,它将执行它并将第一个参数传递给它。
- 当它是一个数字时,它会将两个参数相加并将其作为助手的第一个参数传递。下一次,第一个参数将包含新的总数。
通过这种方式,您可以建立一个连续的 curried 执行链,当函数作为参数传递时该链会终止。
实际的 sum()
函数可以使用助手并通过将第一个参数设置为 0
来初始化链的开始 - neutral element 用于加法运算:
const helper = total => arg => {
if (typeof arg === "function")
arg(total);
else if (typeof arg === "number")
return helper(total + arg);
else
throw new Error("invalid argument");
}
const sum = x =>
helper(0)(x);
sum(result => {console.log("-> ", result)});// -> prints: -> 0
sum(1)(result => {console.log("-> ", result)});// -> prints: -> 1
sum(1)(2)(result => {console.log("-> ", result)});// -> prints: -> 3
sum(1)(2)(4)(result => {console.log("-> ", result)});// -> prints: -> 7
为简单起见,helper()
函数已柯里化。
这里有一个更简洁的版本:
- 假定只会传入数字或函数。
sum()
的定义已减少 eta。
const helper = total => arg =>
(typeof arg === "function")
? arg(total)
: helper(total + arg);
const sum = helper(0);
sum(result => {console.log("-> ", result)});// -> prints: -> 0
sum(1)(result => {console.log("-> ", result)});// -> prints: -> 1
sum(1)(2)(result => {console.log("-> ", result)});// -> prints: -> 3
sum(1)(2)(4)(result => {console.log("-> ", result)});// -> prints: -> 7
我有一个测试,我需要在这种情况下实现一个名为 sum 的高阶函数,它满足以下要求:
sum(result => {console.log("-> ", result)});// -> prints: -> 0
sum(1)(result => {console.log("-> ", result)});// -> prints: -> 1
sum(1)(2)(result => {console.log("-> ", result)});// -> prints: -> 3
sum(1)(2)(4)(result => {console.log("-> ", result)});// -> prints: -> 7
我做了一个函数,以便通过递归获得无限柯里化,但我对回调函数有点迷茫。
let sum = a => !a ? 0 : b => b ? sum(a+b) : a
console.log(sum()) -> 0
console.log(sum(1)()) -> 1
console.log(sum(1)(2)()) -> 3
console.log(sum(1)(2)(4)()) -> 7
使用闭包来累加总和。当内部函数检测到参数是一个函数时,它将调用带有总和的回调。否则它会 return 自己调整和后:
function sum(arg) {
let total = 0;
function inner(arg) {
if (typeof arg === "function") {
arg(total);
} else {
total += arg;
return inner;
}
}
return inner(arg);
}
sum(result => {console.log("-> ", result)});// -> prints: -> 0
sum(1)(result => {console.log("-> ", result)});// -> prints: -> 1
sum(1)(2)(result => {console.log("-> ", result)});// -> prints: -> 3
sum(1)(2)(4)(result => {console.log("-> ", result)});// -> prints: -> 7
如果函数不打算保持状态,则可以使用 this
参数传递总数:
"use strict";
function sum(arg) {
function inner(arg) {
if (typeof arg === "function") {
arg(+this);
} else {
return inner.bind(this + arg);
}
}
return inner.call(0, arg);
}
sum(result => {console.log("-> ", result)});// -> prints: -> 0
sum(1)(result => {console.log("-> ", result)});// -> prints: -> 1
sum(1)(2)(result => {console.log("-> ", result)});// -> prints: -> 3
sum(1)(2)(4)(result => {console.log("-> ", result)});// -> prints: -> 7
const foo = sum(0);
foo(100)(console.log); // 100
foo(1)(console.log); // 1
此处建议使用严格模式,但在草率模式下也可以。在这种情况下,this
参数会再次装箱和拆箱。
为简单起见,您可以有一个接受两个参数的辅助函数。第一个参数是一个数字。第二个参数是一个数字或函数,根据类型它会做不同的事情:
- 当它是一个函数时,它将执行它并将第一个参数传递给它。
- 当它是一个数字时,它会将两个参数相加并将其作为助手的第一个参数传递。下一次,第一个参数将包含新的总数。
通过这种方式,您可以建立一个连续的 curried 执行链,当函数作为参数传递时该链会终止。
实际的 sum()
函数可以使用助手并通过将第一个参数设置为 0
来初始化链的开始 - neutral element 用于加法运算:
const helper = total => arg => {
if (typeof arg === "function")
arg(total);
else if (typeof arg === "number")
return helper(total + arg);
else
throw new Error("invalid argument");
}
const sum = x =>
helper(0)(x);
sum(result => {console.log("-> ", result)});// -> prints: -> 0
sum(1)(result => {console.log("-> ", result)});// -> prints: -> 1
sum(1)(2)(result => {console.log("-> ", result)});// -> prints: -> 3
sum(1)(2)(4)(result => {console.log("-> ", result)});// -> prints: -> 7
为简单起见,helper()
函数已柯里化。
这里有一个更简洁的版本:
- 假定只会传入数字或函数。
sum()
的定义已减少 eta。
const helper = total => arg =>
(typeof arg === "function")
? arg(total)
: helper(total + arg);
const sum = helper(0);
sum(result => {console.log("-> ", result)});// -> prints: -> 0
sum(1)(result => {console.log("-> ", result)});// -> prints: -> 1
sum(1)(2)(result => {console.log("-> ", result)});// -> prints: -> 3
sum(1)(2)(4)(result => {console.log("-> ", result)});// -> prints: -> 7