如何让一个函数调用自己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');