Tagore Smith on functional programming

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.

But today, Togore Smith wrote a brilliantly insightful comment on one of my oldest posts (Closures, finally explained!), and it’s got me thinking about this subject all over again.

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.

 

Advertisement

10 responses to “Tagore Smith on functional programming

  1. Pingback: Chipping the web: January 19th -- Chip's Quips

  2. “The road of excess leads to the palace of wisdom.” . A wonderful quote. I suspect the author built his whole comment around it, just like a short story author would do.

  3. Brendan Miller

    “pure” FP is the same as pure OO. A pain in the ass. The problem is looking at FP or OO as a paradigm, rather than a set of techniques.

    For me, both OO, FP, and old school procedural techniques are on my tool belt, and I pick up the tool that fits the situation best.

    Languages like Scheme or Java that enforce a “paradigm” are good for learning a specific set of techniques. However, I don’t think they are good for solving real problems, where you want to be able to throw the kitchen sink at it. For real software I like kitchen sink languages like CL, C++, Python, and Ocaml.

    Even in C++, you can use FP techniques like higher order functions parameterized by lambdas. In fact, the STL is a generic FP library.

  4. Pingback: » links for 2011-01-20 (Dhananjay Nene)

  5. You made a tactical error trying to learn Scheme as a language, rather than as a teaching tool. You would have done much better with SICP which teaches basic computational theory using Scheme as the language of discussion. That’s why Scheme was invented, as a teaching tool.

  6. Thanks for the kind words- far higher praise than my comment deserved, but appreciated nonetheless.

    I agree with what both Brendan and Kaleberg said, with a couple of caveats. One is that I think there are two Schemes. There is pedagogical Scheme, which is a very small language. Then there are the big modern Scheme implementations, and all the libraries, SRFIs, etc. that can sometimes be made to work with them ;). These Schemes look like kitchen-sink languages to me. I prefer CL to Scheme as a kitchen-sink language, but that is likely more a matter of habit and temperament than anything else.

    Though I prefer kitchen-sink languages for general programming, I have a big soft spot for languages use a very small number of mechanisms. When all you have is a hammer you learn how to turn just about anything into a nail. And in the process you learn that some things that did not initially look very nail-like actually have a lot of nail nature to them.

    Another nice thing about small languages is that if you only have a couple of features there’s a good chance that they will be well-designed. If a language has a lot of features it is very likely that some of them will be badly done.

    More importantly there won’t be impedance mismatch between features, and there won’t be unfortunate compromises meant to diminish impedance mismatch. I think this is part of what Alan Perlis was getting at when he said “It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures. ” There is a lot of power in uniformity- I have a perverse affection for Smalltalk’s arithmetic precedence rules (or lack thereof.)

    My comment was about FP, but I think that it can be generalized a bit. When I see a language that is very small, and that I can’t imagine being able to get anything done in, but I also see a group of very smart and seemingly sane (don’t let that metric discourage you from looking at CL, btw- it’s another kettle of fish entirely) people using that language to do things that look a bit magical, I assume that there’s something important going on. I’d really like to do more Forth sometime- I’ve learned some good things about factoring from the little bit of Forth I’ve done, but… I get the feeling that there are some very interesting ideas that good Forth programmers understand that I don’t.

    SICP is indeed really wonderful in this respect. It will teach you very little Scheme, which is part of the point ;). I’m always amazed by how long it takes them to introduce the few features they do use, and how much they do with so little- even quote isn’t introduced until more than a quarter of the way through the book, IIRC. I think they may talk about Church numerals before they introduce quote, actually even if only in a footnote.

    And Church numerals, or at least the idea behind them, are closely related to what we are talking about here. My original comment was on your article about closures. SICP takes up the topic of functions as first class entities very early (and in fact that was the big aha for me in the Pascal parsing assignment I mentioned. ) It turns out that things like variables are completely unnecessary (theoretically.) In fact, numbers, as independent entities, are unnecessary. If you have function application you can make your own numbers.

    Now no one actually wants to compute with Church numerals, for a host of reasons. But this thing that looks like a theoretical oddity is actually a very pure expression of an idea that is tremendously useful in practice. If you really get the idea behind Church numerals, and figure out how that idea can be practically applied (which is one of the things the first half of SICP is getting at, though not quite as explicitly as might be desired) you will have learned a powerful way of modeling things (one that can and is used in Ruby, btw,) and something really fundamental about computation.

    The one downside of SICP is that, partially because they wanted to avoid introducing distracting features early (like anything not a cons cell, a number, or a function,) and partially because its audience incoming freshmen at MIT it starts off a bit dry if you aren’t all that interested in Newton-Raphson, algorithms for calculating gcds, the golden ratio, numerical integration, etc. It’s a hard book to get into if you lack the interest and/or background to work through a lot of examples that revolve around things like that.

    On the other hand, I tend to think that programmers should be able to handle things like that. I should add that real-valued math has always been a weak point for me, maybe because I dropped out of high school when I was 14. My current work is very heavy on real-valued heavy though (and I often basically fake the math, tbh- geometric intuition for the win,) and makes me acutely aware of how much I should improve my skills in this regard. If you are more used to working with symbols than you are used to devising numeric towers and working out numerical algorithms the first bit of SICP might be just the tonic.

    Anyway, my comment is again very long- I am not good at being pithy, I guess.

  7. Also, wow, grammar fail in so many places in my most recent comment- I’m not actually an illiterate, though I guess I play one on the intertubes. Maybe I should be view this as a lesson on the perils of in-place refactoring of comments with neither unit tests nor preview in place.

  8. I’m not sure if I should comment three times in row on the same post, but I wanted to respond to your update. First off, I’m glad you’ve found my comments interesting. I imagine a lot of people will find them long-winded and overly glib, so it makes me happy that you find them, for all their flaws, interesting enough to quote. From reading your posts it seems like we are interested in a lot of the same problems and, tbh, share a lot of the same biases when it comes to programming.

    As I said via email you’re free to use any comments I make on your blog as the basis for posts of your own. But I think your instinct is right- this is your blog, and your readers come here because they are interested in what you have to say. There are a lot of interesting things that can be said about computing, but there is only one Mike Taylor.

    I’m certainly very flattered that you thought my comment was interesting enough to quote, but I commented on your blog in the first place because it was full of Mike Taylor posts I thought were interesting. If I want a platform to sound off from I can start my own blog, and people who tend to like my posts can follow it. But people come to your blog because they want to read what you write.

    I do think that Kaleberg’s suggestion is very good though. I know you want to do everything (which can mean not having the time to do anything,) but working through SICP is something I think every programmer should do at some point.

    I’d be very interested in seeing a series of posts from you tracking that and I think you might find it a much better way to get at the heart of some of the important ideas of FP (not that SICP is limited to FP) than reading a description of Scheme. SICP is about the big ideas, and I think that not only would you find it very rewarding, you would also find it an endless source of blog-fodder.

  9. Pingback: Tutorial 12b: Too far may not be far enough « Sauropod Vertebra Picture of the Week

  10. Pingback: ALFE design philosophies « Reenigne blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.