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

问题描述 投票:2回答:3

我在代码大战上研究了这个问题一段时间,并使用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));

有没有理由说它不是代码战中的函数?

javascript functional-programming chaining declarative-programming
3个回答
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);

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)有关,以了解折叠函数如何实现链接。


0
投票

ES6中也有同样的想法。 Fun是一系列功能。

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);
© www.soinside.com 2019 - 2024. All rights reserved.