3 ms·
When you say "add complexity", I think you mean "add difficulty". Because for example, a language that has only one-argument functions, and builds multi-arg fun
by Peaker 13y ago
When you say "add complexity", I think you mean "add difficulty". Because for example, a language that has only one-argument functions, and builds multi-arg functions on top is a simpler one than one that has multi-arg functions built-in.
Simplicity is hard -- and pure functional programming is a lot about simplicity, which does make it hard -- hard to learn, and hard to figure out how to tackle various problems.
But the simplicity has many rewards. Mathematical simplicity makes a lot of mathematical deductions tractable -- this is what is typically referred to as "ease of reasoning" about code.
Referential transparency adds a whole lot of ease to the reasoning process.
The pure functional approach also means that type safety goes much further. If you forget to hook up your functions together properly (forget an input, ignore an output) you're likely to get warnings/errors. In the imperative approach, if you forget a side-effecting statement that adds another input to some code, the compiler cannot help you.
Imagine testing -- imperative code requires tests to build up a mock world as input for the code, and then inspect the mock world that results as an output from the code.
Testing a referentially transparent function requires just calling it with differing inputs. It makes property-testing possible, too!
Imagine composition -- pure function composition of two functions composes the meanings of those functions. If those two functions work, so will the composed one.
Try to combine two pieces of imperative code -- that's not necessarily true at all, one might mutate data that's in use by the other. Aliasing issues may arise, etc.
So functional code is easier to reason about, more composable, easier to test, and gets more safety from type checking. It is harder to learn to use, and harder to figure out how to use it to solve certain problems. With time, however, more and more problems yield to the pure functional programming approaches.
- a-nikolaev 13y agoI would like to add that recursive calls can be nicer than loops, when multiple conditions or branching are possible in the loop body. An equivalent implementation with while loops, if conditions, continues, and breaks are usually harder to design correctly than a good recursive function. Functional programming encourages use of small simple datatypes. Tuples instead of small structs. Lists instead of more complex container types. First-class functions instead of classes. However, IMO 'purity' is a bit of a buzzword when applied to functional programming. You may disagree, but that's how I feel about it..
- Peaker 13y agoI think recursive solutions are often very nice indeed. But at worst, recursive solutions are sometimes worse than structured loops, because you can use recursions very much like a free-style goto, allowing your code to have even less restrictive structure than loops. That's why directly recursive code is usually discouraged and reusing recursive combinators is encouraged. I agree that purity is often used as a buzzword. To parody this, Conal Elliott wrote the "C is purely functional" blog post: http://conal.net/blog/posts/the-c-language-is-purely-functional http://conal.net/blog/posts/the-c-language-is-purely-functio... To resolve this, a nice suggestion is to use the term "denotative programming". That is, programming where types and values have mathematically simple denotations that predictably compose exactly according to the syntactic composition being used.
- a-nikolaev 13y agoThanks for the idea of "denotative programming". I think, it can be a really nice paradigm for teaching programming and math together.
- ufo 13y agoTail-recursive calls are essentially gotos, but a little more well behaved (if you try to put state into explicit parameters instead of mutable variables).
- derleth 13y ago> I would like to add that recursive calls can be nicer than loops Having a good library of higher-order functions that encapsulate common recursion patterns is a lot nicer than doing recursion by hand, or having to read code where someone did recursion by hand and you have to not only figure out how the recursion works, but whether the author did anything wrong. Higher-order functions are control structures, and we should encourage their use for all the same reasons we encourage the use of while loops in preference to people building their loop structures by hand out of gotos and conditional gotos.
- eru 13y ago