在codewars上编写一元函数chainer,TypeError但在repl.it上没有错误?

时间:2016-10-07 07:37:18

标签: javascript functional-programming chaining declarative-programming

我在代码大战上解决了这个问题一段时间,并使用repl.it来测试它。它是一个简单的一元函数chainer,但它只适用于repl.it,而codewars在给出这段代码时会给我一个TypeError:

function chained(functions) {
  var funcs = Array.prototype.slice.call(arguments);

  return function (value){

    var finalValue = funcs.reduce(function(prevVal, currFunc){

        return currFunc(prevVal);

    }, value);

    return finalValue;
  }
}

它告诉我currFunc不是一个函数,但使用以下测试代码我在repl.it中运行时得到了正确的答案:

function f1(x){ return x*2 }
function f2(x){ return x+2 }
function f3(x){ return Math.pow(x,2) }
console.log(chained(f1,f2,f3)(0));

为什么它不是代码战中的功能?

3 个答案:

答案 0 :(得分:1)

我不得不在代码大战中查找测试。他们给你这个样板......

function chained(functions) {
  //FIXME
}

查看测试,您可以看到函数正在数组中传递......

Test.assertEquals( chained([f1,f2,f3])(0), 4 )
Test.assertEquals( chained([f1,f2,f3])(2), 36 )
Test.assertEquals( chained([f3,f2,f1])(2), 12 )

你犯的错误是......

var funcs = Array.prototype.slice.call(arguments);

...仅在chained被调用时才有效...

chained(f1,f2,f3)

您的代码可以正常工作并通过代码战中的所有测试。这是完全改变......

function chained(functions) {
  var funcs = Array.prototype.slice.call(arguments);
  return function (value){
    var finalValue = funcsfunctions.reduce(function(prevVal, currFunc){
      return currFunc(prevVal);
    }, value);
    return finalValue;
  }
}

最后,这是我的解决方案^ _ ^

const id = x => x;
const uncurry = f => (x,y) => f (x) (y);
const rcomp = f => g => x => g (f (x));
const chained = fs => fs.reduce(uncurry(rcomp), id);

答案 1 :(得分:0)

虽然@ naomik的解决方案是正确答案并且应该被接受,但我只是想使用老式的ES3分享另一种解决方案:

function chained(functions) {
    return function(x) {
        var fs = functions, i = fs.length, y = x;
        while (i > 0) y = fs[--i](y);
        return y;
    };
}

这只是为了表明在这种特殊情况下你真的不需要使用reduce来编写简洁的代码。此外,使用while循环比使用reduce更有利于性能。最后,这段代码也很容易理解。您不需要精神上与减少iduncurry(rcomp)有关,以了解折叠函数如何实现链接。

答案 2 :(得分:0)

与ES6相同的想法。乐趣是一系列功能。

const chained = fun => {
    return input => {
        return fun.reduce((acc, currentFun) => currentFun(acc), input);
    }
};

,虽然难读但漂亮的现代JS版本:

const chained = fun => input => fun.reduce((acc, currentFun) => currentFun(acc), input);