如何使用Lodash流程组合变化的功能?

时间:2017-02-10 14:38:31

标签: javascript functional-programming lodash composition

我想做一些功能组合。我已经知道了:

如果f3(x)f1(f2(x))相同 然后f3 = _.flowRight(f1,f2);

如果f3(x,y)f1(x, f2(y))相同 那么......?

(用例是node.js / express中间件函数的组合。)

2 个答案:

答案 0 :(得分:4)

  

在下面的图像中,我使用{_}作为值的占位符。把它想象成我们传递内容的代码中的 hole

好吧,让我们想象一下你的功能将要做什么......

a bad dream

  • 这看起来像是一般转换吗?也就是说,你认为我们可以在很多地方使用它吗? - 函数式编程可以促进高度可重用的构建函数,并可以以各种方式进行组合。
  • f1f2之间有什么区别? f1是一个一元函数,只能获得一个arg,f2是一个二元函数,它将获得两个。你会记得哪一个去哪个地方?
  • f1(x)f2的位置是什么?
    • 比较f2(y,f1(x)) ...
    • f2(f1(x),y)
    • 是其中一个比另一个更有用的吗?
    • 你要记住f1的位置吗?

回想一下,函数组合应该能够根据需要将尽可能多的函数链接在一起。为了帮助您理解someFunc的无用性,让我们假设它接受最多3个函数和3个参数。

a nigthmare

  • 这里有模特吗?也许,但是你仍然有一个笨拙的一元函数f1,只有一个arg,而f2f3每个得到2
  • f2f3是否真的需要右侧总是的前一个函数调用的值?
    • 比较f3(z,f2(y,f1(x)))
    • f3(f2(y,f1(x)),z)
    • 也许f3需要左转,但右边是f2个链?
    • 我无法想象你的整个二进制函数API会在同一个地方神奇地需要链式参数
  • 你已经在你的作文中混合了一元二元函数;为什么随意将它限制为那些类型的函数呢? 3个或更多参数的函数怎么样?

答案是自我实现

这里滥用了功能组合。函数组合几乎只有在您组成一元函数(函数接受每个参数)时才有效。当混合更高的功能时,它会立即崩溃并且不能推广。

现在回到您的代码,如果f3需要名称,并且它是f1f2和两个参数的组合,则应明确表示为......

const f3 = (x,y) => f1(x, f2(y))

因为它有很多任意选择,所以不能以任何有用的方式进行推广。只是让它成为现实。

"那么有没有办法构建不同的arity函数?"

当然,有几种不同的实用技巧。我将在此处演示使用高度实用的partial函数



const partial = (f,...xs) => (...ys) => f(...xs, ...ys)

const add = (x,y) => x + y

const mult = (x,y) => x * y

const sq = x => mult (x,x)

// R.I.P. lodash.flowRight
const compose = ([f,...fs]) => x =>
  f === undefined ? x : f (compose (fs) (x))
                  
let f = compose([partial(add, 1), sq, partial(mult, 3)])

console.log(f(2))
// add(1, square(mult(3, 2)))
// add(1, square(6))
// add(1, 36)
// => 37




哦,顺便说一下,我们用一行代码替换了Lodash的flowRight(复杂flow的包装器)。

答案 1 :(得分:2)

听起来你有一个非常具体的要求可能没有lodash等价物。

为什么不为此编写自己的辅助函数?



function composeFuncs(f1, f2) {
  return function(x, y) {
    return f1.call(this, x, f2.call(this, y));
  };
}

var myObj = {
  add: function(val1, val2) {
    return this.myVal + val1 + val2
  },
  mult: function(val) {
    return this.myVal * val
  },
  myVal: 7
};

myObj.newFunc = composeFuncs(myObj.add, myObj.mult);

// 7 + 1 + 7 * 2 = 22
console.log(myObj.newFunc(1, 2));




修改:更新以this方式处理_.flowRight