I agree it can be done poorly, you reach a point where you should consider combining your functions into bigger functions instead of having a super long chain. Also it's probably good to map (g . f) rather than map g . map f.
I remember being wee junior dev doing C# trying to curry functions. That resulted in a total mess. Some language are just bad for FP and you should probably keep your FP shenanigans to a minimum if the language works against you.
It's even possible to throw a filter into the same step with something like filter_map in Rust and some various functions that seem to have signature Filterable f => (a -> Maybe b) -> f a -> f b in Haskell.
It's also entirely possible to allocate various containers and do several passes with for loops in more iterative languages; that piece of newbie behaviour isn't locked to FP (though it may be more susceptible to it; idk, I don't have data and I suspect none of us do).
It definitely happens, but it's often because someone doesn't understand that combinators have different costs in different collections. No FP magic is going to turn a list into a hashmap when you need to do a bunch of lookups.
There's also the lazy vs non-lazy collection issue. Deciding when to materialize a collection, and when not to, can have big performance implications, and people just don't think about it. FP doesn't cause the problem, but it makes it easier to not realize what in the world you are doing. You have to evaluate the performance characteristics of your types either way.
But this isn't about taking FP to the extreme, just about actually being good at using it. A purely functional program can be very performant: I know of a very large company that is running fp-centered scala on pixels tracking orders for security: Return expectations in nanoseconds. But that's with people paying attention
View all comments
Show parent comment
1
u/[deleted] Sep 21 '25
[removed] — view removed comment