| > ...functional programming is mostly about avoiding mutation at all costs Slightly different perspective from Grokking Simplicity[1]: functional programming is not about avoiding mutation because "mutation is bad." In fact, mutation is usually the desired result, but care must be taken because mutation depends on when and how many times it's called. So good FP isn't about avoiding impure functions; instead it's about giving extra care to them. After all, the purpose of all software is to cause some type of mutation/effect (flip pixels on a screen, save bits to storage, send email, etc). Impure functions like these depend on the time they are called, so they are the most difficult to get right. So Grokking Simplicity would probably say this: 1. Avoid pre-mature optimization. The overhead from FP is usually not significant, given the speed of today's computers. Also performance gains unlocked by FP may counter any performance losses. 2. If optimization via mutation is required, push it as far outside and as late as possible, keeping the "core" functionally pure and immutable. This is similar to Functional Core, Imperative Shell[2]; and perhaps similar to options 1 or 2 from the article. [1]: https://www.manning.com/books/grokking-simplicity [2]: https://hw.leftium.com/#/item/18043058 |
(Of course, if you really need impure functions for eg performance, `unsafePerformIO` has you covered in Haskell.)