0

在下面的 Trampoline 代码中,我将从 onclick = export(add,5)视图中的按钮调用。如何确保此调用始终返回值5而不取消注释//x=0下面代码中的行?

var x = 0;

function repeat(operation, num) {
    return function () {
        if (num <= 0) {
            console.log(x);
            // x=0;
            return;
        }
        operation();
        return repeat(operation, --num);
    }
}

function trampoline(fn) {
    while (fn && typeof fn === 'function') {
        fn=  fn();
    }
}

this.export = function (operation, num) {
    trampoline(function () {
        return repeat(operation, num);
    });
}

function add()
{
    ++x;
}

基本上,我想要一个解决方案,其中变量 x 的范围将确保程序在执行 n 次时始终返回相同的输出(换句话说,我想将“导出”设置为纯函数)

4

1 回答 1

1

我不太清楚你在问什么,但你没有理由依赖外部状态、突变或重新分配这个函数。++x并且--n是函数式编程幻想世界中的噩梦——你会希望以几乎任何常见的模式来避免它们。

// checking typeof === 'function' is not really reliable in functional programming
// function return values are perfectly good return types
// use data abstraction to mark tail calls
const trampoline = {
  bounce: (f, x) =>({ isBounce: true, f, x}),
  run: t => {
    while (t && t.isBounce)
      t = t.f(t.x)
    return t
  }
}

// local binding, no mutation, just return x + 1
const add = x => x + 1

// bounced repeat
const repeatAux = (f,n) => x =>
  n === 0 ? x : trampoline.bounce(repeatAux(f, n - 1), f(x))

// this is the function you export
// it runs trampolined repeatAux with initial state of 0
const repeat = (f,n) =>
  trampoline.run(repeatAux(f,n)(0))

// all calls to repeat are pure and do not require external state, mutation, or reassignment
console.log(repeat(add, 5)) // 5
console.log(repeat(add, 5)) // 5
console.log(repeat(add, 7)) // 7
console.log(repeat(add, 7)) // 7

// repeat 1 million times to show trampoline works
console.log(repeat(add, 1e6)) // 1000000


ES5,按要求

var trampoline = {
  bounce: function (f, x) {
    return ({ isBounce: true, f, x})
  },
  run: function (t) {
    while (t && t.isBounce)
      t = t.f(t.x)
    return t
  }
}

var add = function (x) { return x + 1 }

var repeatAux = function (f,n) {
  return function (x) {
    return n === 0
      ? x
      : trampoline.bounce(repeatAux(f, n - 1), f(x))
  }
}

var repeat = function (f,n) {
  return trampoline.run(repeatAux(f,n)(0))
}

console.log(repeat(add, 5)) // 5
console.log(repeat(add, 5)) // 5
console.log(repeat(add, 7)) // 7
console.log(repeat(add, 7)) // 7
console.log(repeat(add, 1e6)) // 1000000

于 2017-05-07T06:44:04.070 回答