遗产
这是数学中的一个概念,称为function composition。
f(x) = y
g(y) = z
g(f(x)) = z
(g•f)(x) = z
最后一行是 "g of f of x equals z"。组合函数的优点在于消除了点。请注意,在 g(f(x)) = z 中,我们采用 x 输入并获得 z 输出。这会跳过中间点y。
Composition 是创建 higher-order functions 并保持代码干净整洁的好方法。很明显我们为什么要在 Javascript 程序中使用它。
补偿
JavaScript 是一种多范式语言,对函数有丰富的支持。我们可以创建一个简单的comp 函数,它结合了两个输入函数g 和f,并产生一个new 函数-
function triple(x) {
return x * 3
}
function plusOne(x) {
return x + 1
}
function comp(g, f) {
return function(x) {
return g(f(x)) // "g of f of x"
}
}
const myfunc =
comp(triple, plusOne)
console.log(myfunc(1))
评估
triple(plusOne(1))
triple(2)
6
撰写
正如问题所暗示的那样,我们很可能想要组合两个以上的功能。下面我们编写compose,它使用输入函数的all 和reduces 使用我们上面的简单comp。如果没有给出函数,我们返回空函数,identity -
const triple = (x) =>
x * 3
const plusOne = (x) =>
x + 1
const comp = (g, f) =>
x => g(f(x)) // "g of f of x"
const identity = (x) =>
x
const compose = (...all) =>
all.reduce(comp, identity)
const myfunc =
compose(triple, triple, plusOne) // any amount of funcs
console.log(myfunc(1))
评估
triple(triple(plusOne(1)))
triple(triple(2))
triple(6)
18
管道
您可以随心所欲地发挥创意。下面,我们写pipe,它允许我们的程序以舒适的从左到右的方向阅读-
const triple = (x) =>
x * 3
const plusOne = (x) =>
x + 1
const pipe = x =>
f => pipe(f(x))
pipe(1)(plusOne)(triple)(triple)(console.log) // 18
pipe(3)(triple)(plusOne)(triple)(plusOne)(console.log) // 31
表达式一的评估 -
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在another Q&A中介绍为$,在这里再次演示-
const $ = x => // "pipe", or whatever name you pick
k => $ (k (x))
const add = x => y => // curried add
x + y
const mult = x => y => // curried mult
x * y
$ (1) // 1
(add (2)) // + 2 = 3
(mult (6)) // * 6 = 18
(console.log) // 18
$ (7) // 7
(add (1)) // + 1 = 8
(mult (8)) // * 8 = 64
(mult (2)) // * 2 = 128
(mult (2)) // * 2 = 256
(console.log) // 256