Ask HN: Functional Programming Differences
22 points| DanielBMarkham | 16 years ago | reply
I've got some good sample code, but my question is this: what are the key things you would tell an imperative programmer about functional programming? I need about a dozen key points to get across before I start drowning them in code.
So far I'm thinking: "start little, grow big", "stay immutable", "factor relentlessly", "learn recursion", and "treat functions as first-class citizens"
Any other blurbs come to mind that capture the differences in thinking between imperative and functional code?
[+] [-] scott_s|16 years ago|reply
I think one of the biggest intellectual hurdles with functional programming is that we know, deep down, that modern computers don't work like that. They do have side-effects and changing, carried state. It's a revelation to realize that the programming model you use to write programs doesn't have to match how the computations will be physically carried out.
[+] [-] alan-crowe|16 years ago|reply
But would supplying code unstick him? It seemed unlikely. Thinking about the equation "Concepts + details = code" I wondered if there was a way of conveying the concepts first, before getting down to the details, and wrote:
Put on your Dijkstra robe, and sit in your arm chair, with a cup of tea, and write on a pad of paper, made from dead tree, using a pen with real liquid ink. This is mathematics not computation :-)
compare this to peano arithmetic If you want to learn recursion you should move quite quickly to writing code because that animates your recursions and clears up any lingering misconceptions. On the other hand, jumping from the words "learn recursion" direct to code is a big leap. Recursion has its own soul, separate from its embodiements in various programming languages.[+] [-] loup-vaillant|16 years ago|reply
If you think "what", recursion is easy. If you think "how", recursion is magic. I think that is the biggest leap. I forgot how I made the jump, however.
[+] [-] unignorant|16 years ago|reply
Closures might be another thing to mention. For instance, you could show how they can be used to implement objects (which should be familiar to C# people).
[+] [-] eru|16 years ago|reply
[+] [-] DanielBMarkham|16 years ago|reply
Great concepts, sure. But in an hour? Might be too much to get their heads around.
One of my code samples is going to be lifted from this great blog entry: http://diditwith.net/2008/03/14/WhyILoveFARefactoringTale.as... where he basically covers some of these concepts by way of example.
I think no matter how I do it, it's going to look (to them) like some hand-waving and magic. Can't really help that, I don't think.
[+] [-] loup-vaillant|16 years ago|reply
Actually, Object oriented programmers already do this. If they use "class polymorphism", "mixins", or any mechanism where an object's method could be determined at runtime, they use first class functions. They just don't know it yet. So, take an example where they would use mixins, then present them a closure or lambda equivalent. That should make functions less scary. (Side note: try to avoid the terms "first class" and "anonymous", "closure", and "lambda". "Ordinary" and "literal" are better, less scary. They point out the fact that functions are as mundane as integers, or strings, so of course they could be parameters or return values.)
"stay immutable"
This is indeed crucial. But effectively impossible until you don't change the way you think. Most imperative programmers think about what the objects should do. Of course, without side effect, they won't do anything, making programming impossible. So they have to think more about what the objects should be. Then, they will be able to avoid side effects until they are really needed.
"factor relentlessly"
Talk about that only when you have talked about functions (don't say "first class"!), as an example of how you could really use them. `sort`, `map` and `filter` would be my favourite examples. Insist on the low syntactic burden of factoring.
[+] [-] scott_s|16 years ago|reply
What you are getting at, though, is that constructs they are already familiar with can be expressed functionally. That is a good point, and it always helps make concepts more concrete when you provide a mapping from current knowledge to new knowledge.
[+] [-] lambdom|16 years ago|reply
(Sorry for my bad english)
[+] [-] skybrian|16 years ago|reply
I like Haskell for the intellectual challenge, but if the aim is to write clear example code that will be understandable to a large audience, you'd be much better off writing it in Python.
[+] [-] dget|16 years ago|reply
Another point I'd consider is "avoid side-effects".
[+] [-] akkartik|16 years ago|reply
[+] [-] caffeine|16 years ago|reply
- Functional design is about breaking a problem up into a series of transformations (functions) on data, rather than modelling object states and behaviors.
- Compose the transformations by treating functions as first-class citizens. Introduce map, filter, foldr, etc. here
- "Functional" = Avoid side-effects! (wrap an I/O layer around your pure core processing instead) Otherwise the composing breaks.
(optional):
- "Start little, grow big", "factor relentlessly" - these are good concepts in ALL programming, and they apply here too.
I think if you just get those points in an hour, along with a nice example (I think F# comes with a web crawler that illustrates all these points), you'll have done very well.
[+] [-] baguasquirrel|16 years ago|reply
[+] [-] ananthrk|16 years ago|reply
[+] [-] icco|16 years ago|reply
[+] [-] lnp|16 years ago|reply
[+] [-] eru|16 years ago|reply
[+] [-] DanielBMarkham|16 years ago|reply
The thing about recursion is that for imperative guys, the first place they go is the for...next loop. Whereas in FP the first place you should go is the built-in stuff like map, fold, etc. But the second place is recursion (with the tail calls done correctly), not for..next
[+] [-] eru|16 years ago|reply
[+] [-] Xichekolas|16 years ago|reply
Also, the ability to reason about your code is a big selling point of side-effect free code. When you don't have to keep track of a bunch of state in your head, it's much easier to reason about what code does, and find any bugs or unexpected behavior.