我想做一些功能组合。我已经知道了:
如果f3(x)
与f1(f2(x))
相同
然后f3 = _.flowRight(f1,f2);
如果f3(x,y)
与f1(x, f2(y))
相同
那么......?
(用例是node.js / express中间件函数的组合。)
答案 0 :(得分:4)
在下面的图像中,我使用
{_}
作为值的占位符。把它想象成我们传递内容的代码中的 hole 。
好吧,让我们想象一下你的功能将要做什么......
f1
和f2
之间有什么区别? f1
是一个一元函数,只能获得一个arg,f2
是一个二元函数,它将获得两个。你会记得哪一个去哪个地方?f1(x)
中f2
的位置是什么?
f2(y,f1(x))
... f2(f1(x),y)
f1
的位置吗?回想一下,函数组合应该能够根据需要将尽可能多的函数链接在一起。为了帮助您理解someFunc
的无用性,让我们假设它接受最多3个函数和3个参数。
f1
,只有一个arg,而f2
和f3
每个得到2 f2
和f3
是否真的需要右侧总是的前一个函数调用的值?
f3(z,f2(y,f1(x)))
f3(f2(y,f1(x)),z)
f3
需要左转,但右边是f2
个链?答案是自我实现
这里滥用了功能组合。函数组合几乎只有在您组成一元函数(函数接受每个参数)时才有效。当混合更高的功能时,它会立即崩溃并且不能推广。
现在回到您的代码,如果f3
需要名称,并且它是f1
,f2
和两个参数的组合,则应明确表示为......
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
。