3 ms·
Because functional programming makes a ton of stuff harder for no benefit. Biggest example is loops.
by millstone 8y ago
Because functional programming makes a ton of stuff harder for no benefit. Biggest example is loops.
- rickycook 8y agowelllll, i definitely wouldn’t say for no benefit... recursion is a much more flexible construct than loops, and when you combine that with pattern matching you can do some really nifty things in a way that’s incredibly easy to reason about and add edge case handling to
- millstone 8y agoEvery mainstream language supports recursion. If it also supports loops, like most do, then loops are used more often, because they're more flexible (example: early-exit).
- tome 8y agoNot every mainstream language supports tail call optimisation. Without TCO, rewriting loops as recursive functions is a bad idea.
- feanaro 8y agoFunctional doesn't imply loops are impossible or even hard. Just to name one possible implementation, if your language supports monads, loops with early returns are trivial.
- millstone 8y agoWell put, this makes my argument in a much better forM_.
- nimih 8y agoTo the contrary: the reduced (heh) power of functional looping constructs is a benefit in and of itself. Explicitly naming and separating patterns of looping such as map, filter, fold/reduce, etc is in some sense a direct application of the rule of least power, and provides two distinct and immediate benefits: First, the purpose and action of the code in question is immediately apparent to the (typically clueless, in my own case) reader. A for (or, heaven forbid, while) loop can do anything at all, but a map is quite explicitly transforming values of a collection (and/or turning them into a collection of side effects), whereas a filter's only job is to, well, filter, and a fold/reduce only needs to be conjured up when the programmer actually needs the full computing power of a generalized aggregation--quite the rare sight when good FP languages and libraries helpfully provide restricted (more descriptive and weaker!) versions such as sum and concatenate. Second, using weaker functions means that the programmer (again, in my case, just an utter rube who needs all the help he can get) is saved from a breathtaking assortment of errors. Even in the chaotic anarchy of a dynamically typed language, a map will ensure you don't make off-by-one errors in your iteration, a pipeline of transformations will let you verify you did your processing in the correct order, and fold will at least give you the friendly encouragement to think hard about your initialization condition, and--more to the point--you won't even have the ability to carry forward state while iterating through a list unless you specifically request it. The general point here, is that functional programming is trying to stop you from thinking about "looping" as a single abstract process, and instead have you explicitly reify the control flow of your program as higher-order function calls: this allows you to be explicit about what is supposed to be happening (to the benefit of both the reader and the writer, listed here in order of importance). Even better, in the presence of a Real Type System, this allows the compiler to actually tell you if your execution logic has the same general shape as your mental model, which is quite frankly a magical feeling once you see it actually happen when solving a difficult problem. That all being said, these benefits aren't free (as can be confirmed by anyone who has read a paper/tutorial on generalized recursion schemes...), so if you're able to write clear, maintainable, descriptive code while avoiding uninitialized states and incorrect boundary conditions and accidentally skipped elements and missing base cases and all the other horrible violence that I, personally and repeatedly, have inflicted on the poor algorithms I've clumsily attempted to implement, shine on you crazy diamond you.