My travails with functional programming have been a bit of a recurring theme on this blog, and I have to admit that my attempt to learn Scheme has stalled, more than anything due to all the other things I’ve been doing. I’m sufficiently aware of it to feel guilty, but not sufficiently to actually invest the time I ought to into actually learning it.
With his kind permission, I am reproducing his comment (lightly edited) here as a new post. So be clear: all the credit for this post belongs to him, not me. (I’ll hang onto the blame, though.) Note, too, that he dashed this off as a comment rather than carefully crafting it as an article … not that you’d know it.
I do think that there are things that are tricky enough to do purely [i.e. “pure” in the sense of “without side effects”] that as a practical matter they shouldn’t be done that way. But I think there is a great deal of value in trying to do things purely even when you find them uncomfortable.
When I first learned Scheme I was pretty much a C programmer (albeit a fairly green C programmer), and we were required to avoid imperative constructs for a lot of our exercises (this was in a really wonderful undergrad class taught by the late, great Robin Popplestone.)
I found a lot of the exercises really uncomfortable, and was annoyed by them. I could have done them very easily iteratively — I remember it taking me a day or so to solve an exercise that I could have written in C in 5 minutes, including debugging.
Later in the semester we were given an exercise that required translating a subset of Pascal to Scheme (or was it the other way around … this was a long time ago), which was pretty heady stuff in my second semester. I realized after doing it that I just would not have been able to do it in C in the amount of time we were given, without it being riddled with bugs — not that it was that hard, but I was pretty inexperienced at C too at that time. A lot of the things I had thought were really awkward to write functionally had become idioms that I now found no harder than the iterative equivalents.
And I could compose these idioms in ways that made things that would have been very hard to get right using imperative idioms run correctly on the first or second try if I understood the problem well enough. In a way, I had pushed the work of correctness to an earlier point in the process- correctness was now mostly determined by how well I had thought through the problem at the outset. If only real-world programming were always like that ;).
A Chinese friend recently asked me to help him understand a line by Blake: “The road of excess leads to the palace of wisdom.” This is an odd sentiment if you come from a culture strongly influenced by Confucianism. This led to a discussion of the idea that you must go too far to know that you have gone far enough, and what that means.
I am convinced that absolutely pure FP is more trouble than it’s worth (leaving aside issues of necessary side-effects like I/O). There is a line, somewhere, where even the best conceivable (human) FP programmer ought to resort to state. But I am also pretty sure that I still find things awkward to do purely that are better done purely. As a pragmatic matter I should certainly not try to do them purely — I have work to do. But I do still work on learning functional idioms for things I would rather do iteratively. I haven’t gone too far yet so I am not sure if I have gone far enough.
That said, if you want a language that is really unbiased take a look at Common Lisp. It does imperative, OO, and FP (with qualifications) natively and I’d argue that it has the best class-based OO system out there. On top of that it is very able to support ideas that it doesn’t do natively.
You can build a language on top of CL with any type system you want, and close to any syntax you want, and have it interoperate seamlessly with the rest of CL, if you have a few years to devote to the task- it just takes that long to build a robust language.
I wonder if you are aware of Qi? It’s an extension to CL with a rich type system (I am really skeptical that crude type systems like those of C++ and Java add safety, but I might be willing to believe that more sophisticated type systems do), and type inference, etc. I haven’t used Qi, so I don’t know if it is practical or not, but I do know that whatever your dream language is it can be built on top of CL as long as you can stomach a leading (or was that trailing…) parenthesis — hard to get rid of that.
It’s too bad that CL has so much historical cruft — much of it doesn’t matter, once you understand CL, but it still makes it annoying to get started with, and these days that is death for a programming language (see the success of PHP, the best web programming language to write Hello World in, and close to the worst for almost any other task.) And some of the cruft really does remain annoying.
Clojure gets rid of a lot of the cruft of CL, but it is not an unbiased language in the way that CL is (not a criticism of Clojure — Clojure is very nice for what it is, but it is not a better CL.) It is opinionated and prefers a functional style. What I would really like for (some) Christmas is a better CL, but there are a lot of reasons that that is not likely to happen — if not for those reasons I would (at least try to) start something like that myself.
In a way, CL reminds me of your posts on the Silmarillion. It is hard enough to get to the meat of it that a lot of people will just abandon the whole thing at the beginning. If it were in my power to republish and re-edit the Silmarillion I would (hypothetically if I were a great editor or a great language designer) fix it, so that the bits most likely to draw you in were at the start, and the bits most likely to send you away were optional. I can’t redo CL or the Silmarillion though — all I can say is that CL is an imperfect and sometimes annoying condensation of a great work, just as the Silmarillion is. I like you, do not use the word “great” lightly here.
Anyway, sorry for the very long comment on an old post. Maybe I should start a programming blog.
Yes, he certainly should start a programming blog!
(I’m particularly fond of the line “I haven’t gone too far yet so I am not sure if I have gone far enough”. I must remember that.)
Update (27 January 2011)
Tagore has added a long and typically insightful comment below, which is well worth reading. Part of me wants to steal it as yet another new article, but there are limits to how much of my blog I should expect commenters to write for me :-) Anyway, even if you don’t read the other comments, page down and read his.