遗产
这是数学中称为函数复合的概念。
f(x) = y
g(y) = z
g(f(x)) = z
(g•f)(x) = z
最后一行读作"g 的 f 的 x 等于 z"。组合函数的好处在于消除了中间点,注意到在g(f(x)) = z
中,我们输入一个x
并得到一个z
输出。这跳过了中间点y
。
组合是创建高阶函数并保持代码简洁的好方法。很明显,我们希望在 JavaScript 程序中使用它。
comp
JavaScript是一种具有丰富函数支持的多范式语言。我们可以创建一个简单的comp
函数,将两个输入函数g
和f
组合在一起,结果是一个新函数 -
function triple(x) {
return x * 3
}
function plusOne(x) {
return x + 1
}
function comp(g, f) {
return function(x) {
return g(f(x))
}
}
const myfunc =
comp(triple, plusOne)
console.log(myfunc(1))
评估
triple(plusOne(1))
triple(2)
6
组合函数
正如问题所示,我们可能需要组合不止两个函数。下面我们编写 compose
函数,它使用上面定义的简单 comp
函数将所有输入函数进行 reduce
操作。如果没有给出任何函数,则返回空函数 identity
。
const triple = (x) =>
x * 3
const plusOne = (x) =>
x + 1
const comp = (g, f) =>
x => g(f(x))
const identity = (x) =>
x
const compose = (...all) =>
all.reduce(comp, identity)
const myfunc =
compose(triple, triple, plusOne)
console.log(myfunc(1))
评估
triple(triple(plusOne(1)))
triple(triple(2))
triple(6)
18
管道
您可以尽情发挥创意。下面,我们编写管道
,使我们的程序能够以舒适的从左到右的方向读取 -
const triple = (x) =>
x * 3
const plusOne = (x) =>
x + 1
const pipe = x =>
f => pipe(f(x))
pipe(1)(plusOne)(triple)(triple)(console.log)
pipe(3)(triple)(plusOne)(triple)(plusOne)(console.log)
表达式一的评估 -
f => pipe(f(1))
pipe(plusOne(1))
f => pipe(f(2))
pipe(triple(2))
f => pipe(f(6))
pipe(triple(6))
f => pipe(f(18))
pipe(console.log(18))
18
另外一个表达式 -
f => pipe(f(3))
pipe(triple(3))
f => pipe(f(9))
pipe(plusOne(9))
f => pipe(f(10))
pipe(triple(10))
f => pipe(f(30))
pipe(plusOne(31))
f => pipe(f(31))
pipe(console.log(31))
31
相关技术
柯里化函数和部分应用是与函数组合相契合的概念。上面的pipe
在另一个问答中被介绍为$
并在这里重新演示 -
const $ = x =>
k => $ (k (x))
const add = x => y =>
x + y
const mult = x => y =>
x * y
$ (1)
(add (2))
(mult (6))
(console.log)
$ (7)
(add (1))
(mult (8))
(mult (2))
(mult (2))
(console.log)
x = function(){return function(b){return b*2}}; x()(2) == 4
...虽然这不是你想要的。 - rafaelcastrocouto