高阶函数与JavaScript的麻烦

时间:2016-03-19 04:25:39

标签: javascript functional-programming

我希望能够使用此createIterator函数运行func n次。

var createIterator = function (func, n) {
  getDouble = function (x) {
    return x + x;
  };

  return getDouble * n;
};

我希望能够使用代码执行此操作:

var getQuad = createIterator(getDouble, 2);
getQuad(2) //8

以下是需要通过的测试:

Test.describe("Iterator for 'getDouble' function", function() {
  var getDouble = function (n) {
  return n + n;
  };

  Test.it("Running the iterator for once", function() {
    var doubleIterator = createIterator(getDouble, 1);

    Test.assertEquals(doubleIterator(3), 6, "Returns double of 3 as 6");
    Test.assertEquals(doubleIterator(5), 10, "Returns double of 5 as 10");
  });

  Test.it("Running the iterator twice", function() {
    var getQuadruple = createIterator(getDouble, 2);

    Test.assertEquals(getQuadruple(2), 8, "Returns quadruple of 2 as 8");
    Test.assertEquals(getQuadruple(5), 20, "Returns quadruple of 5 as 20");
   });
});

我已经有一段时间了,并且无法解决这个问题。任何帮助都是极好的。谢谢!

3 个答案:

答案 0 :(得分:1)

您可以编写一个简单的repeat程序,当应用于nfx时,重复函数的应用 f 参数 x n 次。

// ES6
const repeat = n => f => x =>
  n === 1 ? f(x) : repeat(n-1)(f)(f(x));

const getDouble = x => x * 2;

const double = repeat(1)(getDouble);
const quad = repeat(2)(getDouble);

看到它的工作

console.log(double(3)); // 6
console.log(double(5)); // 10
console.log(quad(2));   // 8
console.log(quad(5));   // 20

让我们逐步评估其中一个例子:

const double = repeat(1)(getDouble);

由于此处已将repeat应用于nf,因此会返回

x => 1 === 1 ? getDouble(x) : repeat(0)(getDouble)(getDouble(x))

现在,当我们打电话

double(3);

3替换为x

1 === 1 ? getDouble(3) : repeat(0)(getDouble)(getDouble(3));

因为1 === 1,返回三元表达式的第一部分

getDouble(3); // 6

回顾:

double(3) === getDouble(3) === 6

现在让我们看一下quad

的相同过程
const quad = repeat(2)(getDouble);

由于此处已将repeat应用于nf,因此会返回

x => 2 === 1 ? getDouble(x) : repeat(1)(getDouble)(getDouble(x))

现在,当我们打电话

quad(2);

2替换x

2 === 1 ? getDouble(2) : repeat(1)(getDouble)(getDouble(2));

因为2 === 1为false,所以返回三元表达式的第二部分

repeat(1)(getDouble)(getDouble(2))
repeat(1)(getDouble)(4)

因此,我们必须使用repeatn=1f=getDouble再次致电x=4,所以

1 === 1 ? getDouble(4) : repeat(0)(getDouble)(getDouble(4))

因为1 === 1,返回三元表达式的第一部分

getDouble(4); // 8

回顾:

quad(2) === getDouble(4) ===  8

如果您需要 ES5 ,请转到

// ES5
var repeat = function repeat(n) {
  return function (f) {
    return function (x) {
      return n === 1 ? f(x) : repeat(n - 1)(f)(f(x));
    };
  };
};

var getDouble = function getDouble(x) {
  return x * 2;
};

var double = repeat(1)(getDouble);
var quad = repeat(2)(getDouble);

console.log(double(3)); // 6
console.log(double(5)); // 10
console.log(quad(2));   // 8
console.log(quad(5));   // 20

最后,

如果你想要原始的API,我认为它是劣等的,我们仍然可以实现

// ES6
const createIterator = (f, n) => x =>
  n === 1 ? f(x) : createIterator(f, n-1)(f(x));

const getDouble = x => x * 2;

const double = createIterator(getDouble, 1);
const quad = createIterator(getDouble, 2);

这是 ES5

// ES5
var createIterator = function createIterator(f, n) {
  return function (x) {
    return n === 1 ? f(x) : createIterator(f, n - 1)(f(x));
  };
};

var getDouble = function getDouble(x) {
  return x * 2;
};

var double = createIterator(getDouble, 1);
var quad = createIterator(getDouble, 2);

两种实现方式相同

为什么repeat(n)(f)(x)更好?

好吧,因为功能完全是咖喱,你可以用有意义的方式部分应用它。

const getDouble = x => x * 2;

const once = repeat(1);
const twice = repeat(2);
const thrice = repeat(3);

const quad = twice(getDouble);
quad(5); // 20

const annoyingAlert = thrice(x => {alert(x); return x;});
annoyingAlert('wake up !'); // displays 'wake up !' three times

您的功能不够灵活,因为它将函数f和次数n作为元组。解决这个问题需要手动调整您的功能或使用Function.prototype.bind黑客。

答案 1 :(得分:-1)

尝试重新排列变量。请注意,getDouble undefined位于var getQuad = createIterator(getDouble, 2); getDouble createIterator



var createIterator = function (func, n) {
  getDouble = function (x) {
    return (x + x) * n;
  };

  return func || getDouble;
};

var getQuad = createIterator(null, 2);
console.log(getQuad(2)) //8




替代地



var createIterator = function(func, n) {
  getDouble = function(x) {
    return x + x;
  };

  return func.bind(null, n * n) || (getDouble(n)) * n;
};

var getQuad = createIterator(function(x) {
  return x + x;
}, 2);

console.log(getQuad(2))




  

我只想运行getDouble n次。

您可以在createIterator内使用循环,将累积值作为createIterator返回的函数中的变量返回,可以乘以传递给getQuad的参数



var createIterator = function(func, n) {

  getDouble = function(x) {
    return x + x;
  };

  var curr = n, res = 0;
  while (--curr) {
    res += func && func(n) || getDouble(n);
  }

  return function(y) {
    return res * y
  }

};

var getQuad = createIterator(null, 2);
console.log(getQuad(5)) // 20




答案 2 :(得分:-1)

你可以这样做,

  1. 创建一个n
  2. 的空数组
  3. 通过函数(参数)
  4. 填充数组
  5. 按运营商加入阵列
  6. 使用连接数组和参数
  7. 创建函数构造函数
  8. 在另一个函数中使用new函数从外部传递参数,然后返回这个新函数。
  9. 我所说的代码片段在这里(如果您的浏览器支持Array.prototype.fill)

    
    
    var createIterator = function (func, n, operator) {
      operator = operator || "+";
      var inner = Function(["f", "a"], "return " + Array(n ).fill("f(a)").join(operator) + ";");
      return function (arg) {
        return inner(func, arg);    
      };
    };
    
    
    var c = createIterator(function (n) {return n + n;}, 2);
    
    document.write(c(3) + "<br/>");
    
    document.write(c(6) + "<br/>");
    
    
    var d = createIterator(function (n) {return n + n;}, 3, "+");
    
    document.write(d(3) + "<br/>");
    
    document.write(d(6) + "<br/>");
    &#13;
    &#13;
    &#13;

    否则请使用此代码段

    &#13;
    &#13;
    var createIterator = function (func, n, operator) {
      operator = operator || "+";
      var array = [];
      for (var i = 0; i < n; i += 1) {array[i] = "f(a)";}
      var inner = Function(["f", "a"], "return " + array.join(operator) + ";");
      return function (arg) {
        return inner(func, arg);    
      };
    };
    
    
    var c = createIterator(function (n) {return n + n;}, 2);
    
    document.write(c(3) + "<br/>");
    
    document.write(c(6) + "<br/>");
    
    
    var d = createIterator(function (n) {return n + n;}, 3, "+");
    
    document.write(d(3) + "<br/>");
    
    document.write(d(6) + "<br/>");
    &#13;
    &#13;
    &#13;