JavaScript 函数式编程03-组合与管道

compose and pipe

函数式编程就是将每个不同的计算部分分散封装到不同的函数内,等到使用的时候再一一拿出来并按照一定的顺序进行执行,就类似于管道一样,共同组合成一个完整的函数。

组合:每个程序的输出可以是另一个程序的输入,每个基础命令结合起来即可完成复杂的任务。

例如:处理数组 let arr = [2, 3, 7, 8]; 将其中大于5的值取出来并减一,可以使用:

1
map(filter(arr, i => i > 5), i => i-1)

如上,filter的输出作为map函数的输入,两个函数组合起来可以轻易解决某些问题。数据就像是在管道内流动一样,从出口到另一个入口。那我们便可以抽象出代码逻辑,让我们不再关心中间状态,只需要输入初始数据即可,实现的类似这样的函数被称为 compose 函数

1
const compose = (a, b) => c => a(b(c));

利用compose可以实现有趣的事情:

1
2
3
4
5
6
const str2num = s => parseInt(s);
const int = n => Math.floor(n);

const str2int = compose(int, str2num);

str2int("3.1415926"); // 3

如果使用 compose 函数来解决多参数函数问题比较麻烦,需要借助偏函数来实现。(你可以将其中的偏函数变体单独储存为一个函数,方便语义化)具体实现如下:

1
compose(partial(map)(i => i-1), partial(filter)(i => i > 5))(arr);

偏函数、map、filter等函数之前的文章已给出代码实现!

可能你会想,实现它有什么用?直接将所有代码都封装进一个函数不就行?

是的,在某些人看来,命令式的做法更方便、更符合思考逻辑。但是当你阅读别人的代码,或者阅读自己好长时间前写的代码时,命令式的代码需要一定的时间去理清其中的逻辑,而函数是的编程则很好看懂其中逻辑(_或许在您看来命令式更易懂或者在于函数命名是否清除_)。而且,函数式的代码易于写测试代码,您可以将每一部分都单独进行测试,而当您重新写一个函数的时候,复用这些小函数可以安全使用,因为它们已被测试安全!

组合与管道

上面实现的 compose 函数只能实现两个函数的组合,为了实现多个参数的组合,需要重写函数。实现逻辑是将给定的函数参数数组整合为一个并返回,这可以利用 reduce 来实现:

1
const compose = (...func) => value => reduce(func.reverse(), (acc, fn) => fn(acc), value);

使用:

1
2
compose(partial(map)(i => i-1), partial(filter)(i => i > 5), partial(map)(i => i + 3))(arr);
// => [ 5, 9, 10 ]

实现到这,你可能会发掘 compose 函数中数据流是从右到左流,而不是从左到右。而似乎从左到右执行似乎才符合逻辑,这样数据流从左到右的函数则被称为 pipe 管道函数。其实现方式类似于compose:

1
const pipe = (...func) => value => reduce(func, (acc, fn) => fn(acc), value);

使用管道解决问题:

1
2
pipe(partial(map)(i => i + 3), partial(filter)(i => i > 5), partial(map)(i => i-1))(arr);
// => [ 5, 9, 10 ]

组合 compose 与管道 pipe 是相似的,他们只是数据流的方向相反,作用是一致的,都是整合小的函数,实现完整的功能。

使用组合与管道,是有利于调试的,数据在不同的函数中流动,你完全可以在任何地方加一个拦截器调试数据:

1
2
3
4
const log = data => {
console.log(data);
return data;
}

拦截数据:

1
2
3
pipe(partial(map)(i => i + 3), 
log, // 输出:[ 5, 6, 10, 11 ]
partial(filter)(i => i > 5), partial(map)(i => i-1))(arr);

这对于调试代码、定位bug等有很大的帮助。

JavaScript 函数式编程
作者:Kart Jim
链接:https://github.com/can-dy-jack/delicate/2023/02/15/js函数式编程/JavaScript 函数式编程03-组合与管道/
来源:Hexo
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 许可协议。著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
长风破浪会有时,直挂云帆济沧海