如何在另一个FP中组合功能?

时间:2017-03-13 12:41:15

标签: javascript functional-programming ecmascript-6

我正在学习JavaScript中的函数编程,目前我有以下代码。

我想将这两个函数组合在另一个函数中,该函数让用户传递一个值并使结果等于传递的值加上10乘以3使用以下函数。

伪代码示例:

 const myFormulat= add(10).multiply(3);

如何仅使用vanilla JS ES6编写此功能?

function add(x){
  return function(y){
    return y + x;
  };
}

function multiply(x){
  return function(y){
    return y * x;
  };
}

// my calculation
// get x add 10 and after multiply by 3

3 个答案:

答案 0 :(得分:5)

熊陷阱和地雷

这个答案的存在只是为了说明为什么这不是一个好主意 - 复杂性是通过屋顶,基本上没有收获。注意我们必须告诉我们函数何时结束,所以我添加了一个特殊函数call所以我们的表达式看起来像这样

.add(3).mult(4).call(x)
// where x is the input for the entire function chain

最后一项更改是我们的函数库addmult等等必须包含在限制代理范围的范围内。该范围告诉我们我们希望链接的功能的确切位置。

哦,如果这部分的标题不够警告,我们也会使用Proxy

// helpers
const identity = x => x
const comp = f => g => x => f(g(x))

// magic wand
const using = scope => {
  let acc = identity
  let p = new Proxy({
    call: x => acc(x),
  }, {
    get: (target, name) => {
      if (name in target)
        return target[name]
      else if (name in scope)
        return x => {
          acc = comp (scope[name](x)) (acc)
          return p
        }
      else
        throw Error(`${f} is not undefined in ${scope}`)
    }
  })
  return p
}

// your functions wrapped in a scope
const math = {
  add: x => y => x + y,
  mult: x => y => x * y
}

// chain it up
const main = using(math).add(3).mult(4).add(5).mult(6).call

console.log(main(2))
// (((2 + 3) * 4) + 5) * 6
// ((5 * 4) + 5) * 6
// (20 + 5) * 6
// 25 * 6
// 150

功能组合

但严重的是,不要这样做。考虑到你的起点,通过.运算符推送所有内容是不自然的,你应该寻找更有效的方法来组合函数。

我们可以使用稍微不同的表示法有效地做同样的事情 - 这里最大的区别是复杂性几乎是

const compose = (f,...fs) => x =>
  f === undefined ? x : compose (...fs) (f(x))
  
const add = x => y => x + y

const mult = x => y => x * y

const main = compose (add(3), mult(4), add(5), mult(6))

console.log(main(2)) // => 150

<强>函子

也许你不喜欢传统的功能组合,这很好,因为我们还有另一种方法来解决这个问题,使用 Functors - 简单地说,一个Functor是具有map功能的容器。

下面我们有一个Box函数,它将值放在我们的容器中。 map函数接受一个函数,并使用用户指定函数的返回值创建一个新Box。最后,我们有一个fold函数,它允许我们将 out 的值带出去

同样,它改变了我们编写代码的方式,但减少的复杂性是巨大的(与代理示例相比)

const Box = x => ({
  map: f => Box(f(x)),
  fold: f => f(x)
})

const add = x => y => x + y

const mult = x => y => x * y

const main = Box(2).map(add(3)).map(mult(4)).map(add(5)).map(mult(6)).fold

main(console.log) // 150

答案 1 :(得分:1)

请参阅:http://scott.sauyet.com/Javascript/Talk/Compose/2013-05-22/

function add(x){
  return function(y){
    return y + x;
  };
}

function multiply(x){
  return function(y){
    return y * x;
  };
}

Function.prototype.compose = function(g) {
     var fn = this;
     return function() {
         return fn.call(this, g.apply(this, arguments));
     };
};

var f = multiply(3).compose(add(10));

console.log(f(5));

答案 2 :(得分:0)

如果我理解你正确,你试图找出JavaScript中的函数链

功能链接或方法链接是JS世界中常见的模式。

您可以实现链接的方法之一是创建一个类并返回此运算符或当前对象引用

您可以在以下网址

中找到有关此内容的有趣教程

https://www.bennadel.com/blog/2798-using-method-chaining-with-the-revealing-module-pattern-in-javascript.htm