I disagree with this article.
We shouldn't sacrifice readability and composability for performance gains, and we don't have to.
Our goal here is to iterate over things in a way that is both readable and performant. Let's have a look at different methods of achieving this.
We want to multiply stuff by 2, and then add 4. Let's define these goals as functions:
constmulByTwo=(n=>n*2);constaddFour=(n=>n+4);
This, as mentioned in the article, is readable, but may become a performance issue:
[1,2,3].map(mulByTwo).map(addFour);
The proposed solution, however, is not very readable, and doesn't scale/compose well:
[1,2,3].map(n=>n*2+4);
This uses composition, but is far from being readable because of the
reversed, "inside-out" order of execution
[1,2,3].map(n=>addFour(mulByTwo(n)));
Solution? Best of both worlds. Let's create a higher-order function which would allow us to pipe
other function calls in a nice, clean, left-to-right order:
In fact, multiple functional/semi-functional libraries have pipe function in their toolbelt. it's also a part of my very minimal fp library.
We can as well define all, some or none functions and use them to compose our filter logic.
Now this is an elegant solution. The only problem with it is that it isn't exactly the most beginner-friendly code. You must have a significant amount of experience with functional programming to be able to fathom the notion of functions inside functions inside functions for composition.
Besides that, it really is an elegant solution that combines the best of both worlds. Pipes truly are a marvel of (software) engineering.
isn't exactly the most beginner-friendly code. (...) Pipes truly are a marvel of (software) engineering.
Maybe it's because I started out learning programming from the FP side, but composition feels like pretty intuitive beginner stuff, and I've always had trouble reading ugly loops which store all kinds of stuff in variables.
I think "beginner friendly" highly depends on what you've been exposed to so far.
Yuppp, loops are always ugly. There is no question about that. You have no idea how many times I've gotten myself inside infinite loops. It's just a horrible experience when I was a beginner.
And I think you're right about that. It does depend on what you've been exposed to as a beginner.
This is a bit like saying that nails are always ugly, you should use screws. Beginners should learn when to use which, in addition to how not to hit their fingers.
FP is cool and all but FP in JS has become an unbearable infomercial lately: "Have you suffered from infinite loops? Ever feel like your code doesn't have enough dots or arrows? Tired of using plus signs for addition? Try FP"
What is the performance of this solution?
Because this will be guaranteed slower than the solution in the artice because the JavaScript engine almost certainly doesn't do functional optimization. (+ You create a capture witch is slow, needs more optimization which adds to potential jit time)
It is also less simple as you have to understand more concepts to understand the code, especially because JS is an imperative language the functional style is a bad fit. In imparative languages a for-loop with the proper if-statements and calculations will always be the better option for both performance and simplicity.
Please don't bully my phone's battery more than JS already has to. :)
I also make args unary, so that I don't have to think about methods like map injecting spurious parameters.
Next comes giving it a TS type signature.
Which involves overloads.
It's horrible, but the results are great.
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
I disagree with this article.
We shouldn't sacrifice readability and composability for performance gains, and we don't have to.
Our goal here is to iterate over things in a way that is both readable and performant. Let's have a look at different methods of achieving this.
We want to multiply stuff by 2, and then add 4. Let's define these goals as functions:
This, as mentioned in the article, is readable, but may become a performance issue:
The proposed solution, however, is not very readable, and doesn't scale/compose well:
This uses composition, but is far from being readable because of the
reversed, "inside-out" order of execution
Solution? Best of both worlds. Let's create a higher-order function which would allow us to pipe
other function calls in a nice, clean, left-to-right order:
We can now do stuff!
In fact, multiple functional/semi-functional libraries have
pipe
function in their toolbelt. it's also a part of my very minimal fp library.We can as well define
all
,some
ornone
functions and use them to compose ourfilter
logic.Now this is an elegant solution. The only problem with it is that it isn't exactly the most beginner-friendly code. You must have a significant amount of experience with functional programming to be able to fathom the notion of functions inside functions inside functions for composition.
Besides that, it really is an elegant solution that combines the best of both worlds. Pipes truly are a marvel of (software) engineering.
Maybe it's because I started out learning programming from the FP side, but composition feels like pretty intuitive beginner stuff, and I've always had trouble reading ugly loops which store all kinds of stuff in variables.
I think "beginner friendly" highly depends on what you've been exposed to so far.
Yuppp, loops are always ugly. There is no question about that. You have no idea how many times I've gotten myself inside infinite loops. It's just a horrible experience when I was a beginner.
And I think you're right about that. It does depend on what you've been exposed to as a beginner.
This is a bit like saying that nails are always ugly, you should use screws. Beginners should learn when to use which, in addition to how not to hit their fingers.
FP is cool and all but FP in JS has become an unbearable infomercial lately: "Have you suffered from infinite loops? Ever feel like your code doesn't have enough dots or arrows? Tired of using plus signs for addition? Try FP"
What is the performance of this solution?
Because this will be guaranteed slower than the solution in the artice because the JavaScript engine almost certainly doesn't do functional optimization. (+ You create a capture witch is slow, needs more optimization which adds to potential jit time)
It is also less simple as you have to understand more concepts to understand the code, especially because JS is an imperative language the functional style is a bad fit. In imparative languages a for-loop with the proper if-statements and calculations will always be the better option for both performance and simplicity.
Please don't bully my phone's battery more than JS already has to. :)
Funny, I usually define my pipe as following:
I also make args unary, so that I don't have to think about methods like
map
injecting spurious parameters.Next comes giving it a TS type signature.
Which involves overloads.
It's horrible, but the results are great.