如何让一个函数调用自己n次
How to make a function call itself n times
假设我有一个名为 f 的函数,它接受一个名为 x 的整数参数和 returns 一个整数。我还有一个整数 n 表示函数必须调用自身的次数。因此,例如,如果我的函数调用在 n = 1 时看起来像这样 f(x)
,那么当 n = 3 时它看起来像这样 f(f(f(x)))
。在我的示例中怎么会这样:
function succ(n) {
return function (f, x) {
return f(x);
};
}
你可以在内部函数中循环:
for(let i = 0; i < n; i++) x = f(x);
return x;
或者让您的函数自行调用:
return n > 0 ? succ(n - 1)(f, f(x)) : x;
我们可以核心递归地表达这个算法。 Corecursion 将其结果建立在从起点前进的道路上:
const iterate = f => x =>
[x, () => iterate(f) (f(x))];
const main = iterate(x => x * 2) (1);
console.log(
main[1] () [1] () [1] () [1] () [1] () [1] () [1] () [1] () [0]); // 256
这只是概念验证,并非我们真正想要的。我们如何避免笨拙的界面?我们可以使用 Proxy
使非参数函数隐式化。它与惰性 属性 吸气剂的机制基本相同。此外,我们不想手动访问流中的值,而是为了方便使用一个函数:
class ThunkProxy {
constructor(f) {
this.memo = undefined;
}
get(g, k) {
if (this.memo === undefined)
this.memo = g();
if (k === THUNK)
return true;
else if (k === Symbol.toPrimitive)
return () => this.memo;
else if (k === "valueOf")
return () => this.memo;
else return this.memo[k];
}
}
const THUNK = "thunk";
const thunk = f =>
new Proxy(f, new ThunkProxy(f));
const iterate = f => x =>
[x, thunk(() => iterate(f) (f(x)))];
const takeNth = n => ([head, tail]) =>
n === 0
? head
: takeNth(n - 1) (tail);
const main = iterate(x => x * 2) (1);
console.log(
main[1] [1] [1] [1] [1] [1] [1] [1] [0]); // 256
console.log(
takeNth(16) (main)); // 65536
您可以构建一个 times
高阶函数并用它来包装其他函数...
const times = (fn, n) => (...args) => {
if (!n) { return; }
fn(...args);
return times(fn, n - 1)(...args);
}
const log10 = times(console.log, 10);
log10('hello');
假设我有一个名为 f 的函数,它接受一个名为 x 的整数参数和 returns 一个整数。我还有一个整数 n 表示函数必须调用自身的次数。因此,例如,如果我的函数调用在 n = 1 时看起来像这样 f(x)
,那么当 n = 3 时它看起来像这样 f(f(f(x)))
。在我的示例中怎么会这样:
function succ(n) {
return function (f, x) {
return f(x);
};
}
你可以在内部函数中循环:
for(let i = 0; i < n; i++) x = f(x);
return x;
或者让您的函数自行调用:
return n > 0 ? succ(n - 1)(f, f(x)) : x;
我们可以核心递归地表达这个算法。 Corecursion 将其结果建立在从起点前进的道路上:
const iterate = f => x =>
[x, () => iterate(f) (f(x))];
const main = iterate(x => x * 2) (1);
console.log(
main[1] () [1] () [1] () [1] () [1] () [1] () [1] () [1] () [0]); // 256
这只是概念验证,并非我们真正想要的。我们如何避免笨拙的界面?我们可以使用 Proxy
使非参数函数隐式化。它与惰性 属性 吸气剂的机制基本相同。此外,我们不想手动访问流中的值,而是为了方便使用一个函数:
class ThunkProxy {
constructor(f) {
this.memo = undefined;
}
get(g, k) {
if (this.memo === undefined)
this.memo = g();
if (k === THUNK)
return true;
else if (k === Symbol.toPrimitive)
return () => this.memo;
else if (k === "valueOf")
return () => this.memo;
else return this.memo[k];
}
}
const THUNK = "thunk";
const thunk = f =>
new Proxy(f, new ThunkProxy(f));
const iterate = f => x =>
[x, thunk(() => iterate(f) (f(x)))];
const takeNth = n => ([head, tail]) =>
n === 0
? head
: takeNth(n - 1) (tail);
const main = iterate(x => x * 2) (1);
console.log(
main[1] [1] [1] [1] [1] [1] [1] [1] [0]); // 256
console.log(
takeNth(16) (main)); // 65536
您可以构建一个 times
高阶函数并用它来包装其他函数...
const times = (fn, n) => (...args) => {
if (!n) { return; }
fn(...args);
return times(fn, n - 1)(...args);
}
const log10 = times(console.log, 10);
log10('hello');