javascript编写
compose
, and especially pipe
, are easily among my favorite functions.
我最喜欢的功能很容易是compose
,尤其是pipe
。
This article’s just to have fun and explore different implementations of these two gems. I recommend you understand what they do before reading this; perhaps check out my deep-dive here.
本文只是为了娱乐并探索这两个瑰宝的不同实现。 我建议您在阅读本文之前先了解他们的工作; 也许在这里看看我的深入研究 。
pipe = (...fns) => (x) => fns.reduce((v, f) => f(v), x);
Classic.
经典。
Starting with the leftmost function, reduce an array of functions to a single value by calling the next function with the previous one’s output.
从最左边的函数开始,通过使用前一个函数的输出调用下一个函数,将函数数组减少为单个值。
double = (x) => x * 2;
add1 = (x) => x + 1;
pipe(
double,
add1
)(100); // 201
I discovered this implementation through Eric Elliott, and wrote a deep-dive on it here.
我通过埃里克·埃利奥特 ( Eric Elliott)发现了此实现,并在此处对此进行了深入研究。
Use reduceRight
to implement compose
. Now your functions are called from right, to left.
使用reduceRight
实现compose
。 现在,您的函数从右到左调用。
compose = (...fns) => (x) => fns.reduceRight((v, f) => f(v), x);
compose(
double,
add1
)(100);
// 202
You could also reverse fns
and keep using reduce
(less performant).
您还可以反转fns
并继续使用reduce
(性能较低)。
compose = (...fns) => (x) => fns.reverse().reduce((v, f) => f(v), x);
compose(
double,
add1
)(100); // 202
reverse
mutates the array, though, so you might copy it first (even less performant).
但是, reverse
改变数组,因此您可以先复制它(甚至降低性能)。
compose = (...fns) => (x) => [...fns].reverse().reduce((v, f) => f(v), x);
compose(
double,
add1
)(100); // 202
Use reduceRight
to go back to pipe
.
使用reduceRight
返回pipe
。
pipe = (...fns) => (x) => [...fns].reverse().reduceRight((v, f) => f(v), x);
pipe(
double,
add1
)(100); // 201
但他们都是一元的 (But They’re All Unary)
All the above snippets, by the way, are unary. Each function may only accept a single argument.
顺便说一下,以上所有片段都是一元的 。 每个函数只能接受一个参数 。
If your pipeline’s first function must be nAry (accepting n
arguments), try this implementation:
如果管道的第一个函数必须为nAry (接受n
参数),请尝试以下实现:
multiply = (x, y) => x * y;
pipe = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)));
pipe(
multiply,
add1
)(10, 10); // 101
// Takes multiple args now
This snippet’s from 30secondsofcode.org. Your first (leftmost) function may accept n
arguments–all others must be unary.
该代码段来自30secondsofcode.org 。 您的第一个(最左侧)函数可以接受n
参数-所有其他参数都必须是一元的。
Again, reduceRight
gives us compose
. Now your rightmost function may accept n
arguments. Let’s move multiply
to the end of the chain.
同样, reduceRight
给我们compose
。 现在,您最右边的函数可以接受n
参数。 让我们将multiply
移动到链的末尾。
compose = (...fns) => fns.reduceRight((f, g) => (...args) => g(f(...args)));
compose(
add1,
multiply
)(10, 10); // 101
// Takes multiple args now
// Put multiply first
Like before, you could reverse the fns
array and keep using reduce
:
和以前一样,您可以反转fns
数组并继续使用reduce
:
compose = (...fns) =>
[...fns].reverse().reduce((f, g) => (...args) => g(f(...args)));
compose(
add1,
multiply
)(10, 10); // 101
If you want to keep reduce
without the slight performance hit, just switch g
and f
:
如果您想在不reduce
性能的情况下保持reduce
性能,只需切换g
和f
:
compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));
compose(
add1,
multiply
)(10, 10); // 101
And use reduceRight
to switch back to pipe
.
并使用reduceRight
切换回pipe
。
pipe = (...fns) => fns.reduceRight((f, g) => (...args) => f(g(...args)));
pipe(
multiply,
add1
)(10, 10); // 101
// put multiply first now
结论 (Conclusion)
Phew! That’s a lot of ways to pipe and compose!
! 有很多管道和组成方式!
It just proves that, no matter what, you must loop over an array of functions, calling the next one with the previous one’s result.
事实证明,无论如何,您都必须遍历一组函数,并用前一个的结果调用下一个函数 。
Doesn’t matter if you use reduce
, reduceRight
, switch the invocation order, or whatever else.
不管您使用reduce
, reduceRight
,切换调用顺序或其他任何方式都没有关系。
If you want
pipe()
, go left-to-right. Want compose()? Go right-to-left.如果需要
pipe()
,请从左到右移动。 需要compose()吗? 从右到左。
Plain and simple. Until next time!
干净利落。 直到下一次!
翻译自: https://www.freecodecamp.org/news/10-ways-to-write-pipe-compose-in-javascript-f6d54c575616/
javascript编写