如何使用 Lodash 流组合不同数量的函数? [英] How to compose functions of varying arity using Lodash flow?
问题描述
我想做一些函数组合.我已经知道了:
I want to do some function composition. I know already this:
如果 f3(x)
应与 f1(f2(x))
相同然后 f3 = _.flowRight(f1,f2);
If f3(x)
shall be the same as f1(f2(x))
then f3 = _.flowRight(f1,f2);
如果 f3(x,y)
应与 f1(x, f2(y))
相同那么……?
If f3(x,y)
shall be the same as f1(x, f2(y))
then …?
(用例是node.js/express中间件函数的组合.)
(The use case is the composition of node.js/express middleware functions.)
推荐答案
在以下图像中,我使用
{_}
作为值的占位符.把它想象成代码中的一个洞,我们可以在其中传递一些东西.
In the following images, I use
{_}
as a placeholder for a value. Think of it as a hole in the code where we pass something in.
好吧,让我们想象一下你的函数必须做什么......
Ok let's imagine what your function would have to do...
- 这看起来像一个通用的转换吗?即,您认为我们可以在很多地方使用它吗?–函数式编程促进构建高度可重用且可以多种方式组合的函数.
f1
和f2
有什么区别?f1
是一个只能得到一个参数的一元函数,f2
是一个可以得到两个参数的二元函数.你会记得哪个去哪个地方吗?- 什么控制了
f1(x)
在f2
中的位置?- 比较
f2(y,f1(x))
... - 到
f2(f1(x),y)
- 其中一个比另一个更有用吗?
- 你会记住
f1
的位置吗?
- Does this seems like a generic transformation? ie, do you think we can use this in many places? – functional programming promotes building functions which are highly reusable and can be combined in various ways.
- What is the difference between
f1
andf2
?f1
is a unary function which will only get one arg,f2
is a binary function which will get two. Are you going to remember which one goes in which place? - What governs the position that
f1(x)
gets placed inf2
?- Compare
f2(y,f1(x))
... - to
f2(f1(x),y)
- is one of those more useful than the other?
- are you going to remember which position
f1
gets?
回想一下,函数组合应该能够将任意数量的函数链接在一起.为了帮助您理解
someFunc
的无用性,让我们假设它最多接受 3 个函数和 3 个参数.Recall that function composition should be able to chain as many functions together as you want. To help you understand the futility of
someFunc
, let's imagine it accepting up to 3 functions and 3 arguments.- 这里还有模式吗?也许吧,但你仍然有笨拙的一元函数
f1
,它只得到一个 arg,而f2
和f3
每个得到 2 f2
和f3
是否真的需要总是 右侧的前一个函数调用的值?- 比较
f3(z,f2(y,f1(x)))
- 到
f3(f2(y,f1(x)),z)
- 也许
f3
需要从左边链接,但f2
从右边链接? - 我无法想象你的整个二元函数 API 会神奇地需要在同一个地方链接参数
- Is there even a pattern here? Maybe, but you still have the awkward unary function
f1
that only gets one arg, whilef2
andf3
each get 2 - Is it true that
f2
andf3
are going need the value of the previous function calls on the right side always ?- Compare
f3(z,f2(y,f1(x)))
- to
f3(f2(y,f1(x)),z)
- Maybe
f3
needs to chain left, butf2
chains from the right? - I can't imagine your entire API of binary functions would magically need chained arguments in the same place
答案是自我实现
函数组合在这里被滥用.函数组合几乎只在您组合一元函数时才有效(每个函数接受 1 个参数).当混入更高数量的函数时,它立即崩溃并且无法推广.
Function composition is being misused here. Function composition pretty much only works when you're composing unary functions exclusive (functions accepting 1 argument each). It immediately breaks down and cannot be generalised when mixing in functions of higher arity.
现在回到你的代码,如果
f3
需要一个名字,它是f1
、f2
和两个参数的组合,它应该清楚地表达为…Going back to your code now, if
f3
needs a name and it is the combination off1
,f2
, and two parameters, it should be plainly expressed as …const f3 = (x,y) => f1(x, f2(y))
因为它做出了如此多的任意选择,所以不能以任何有用的方式概括.就这样吧.
Because it makes so many arbitrary choices, it cannot be generalized in any useful way. Just let it be as it is.
那么有没有办法组合不同数量的函数?"
当然,有几种不同实用性的技术.我将在这里演示高度实用的
partial
函数的使用Sure, there are a couple techniques of varied practicality. I'll demonstrate use of the highly practical
partial
function hereconst 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
) 与一行代码.Oh, by the way, we replaced Lodash's
flowRight
(wrapper of the complexflow
) with a single line of code.这篇关于如何使用 Lodash 流组合不同数量的函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- Compare
- 比较
- Compare
- 比较