What killed Lisp could kill Haskell as well. May 9, 2009 | 07:25 pm

This blog post is mainly aimed at the functional programmer readership of this blog. There is a video out there on the web from a recent conference that brings up a number of good points, that I think needs to be more widely disseminated in the functional community.

Now, before I link to the video and have you go watch it, I need to do a little bit of explaining. Because, you see, the conference was RailsConf. And the presenter doesn’t even mention functional programming, and his discussion, well, mention really, of static typing encompasses Java, C#, and C++, and that’s it. In fact, the original title is “What killed Smalltalk could kill Ruby as well”. But as you listen to the video, I want you to do the following: when he says “Smalltalk”, think “Lisp”. When he says “Ruby”, think “Haskell”. And when he says “Test Driven Development/Design”, think “Static Typing”. Some of the details don’t map perfectly, but his main points are, I think spot on.

So, with that in mind, go watch.

That is all.

  • http://clubjuggler.com/ Tanner Lovelace

    I wasn’t aware that Lisp was dead. And, really, isn’t comparing Haskell to Ruby just a bit of delusions of grandeur?

  • http://www.bluetrainsoftware.com Richard Vowles

    Tanner – did you watch the presentation (and read the response from James Robertson)? The argument is simply that Smalltalk is not being used for a statistically significant set of industry problems (much like Lisp isn’t, nor Clojure perhaps its most recent reincarnation) because it was too easy to make a mess in that you didn’t have to clean up before it got unusable. Lisp clearly isn’t “dead”, some people use it, but probably about the same number as Smalltalk – but the concepts are being used and morphed into other languages. I podcast with a friend who is a major Lisp fancier but he said he wouldn’t write a commercial app in it.

    My response to Robert’s comment about Haskell is – is Haskell even alive? Didn’t Scala provide a “good enough” alternative for functional programmers? Haskell is more like C++, people who understand it have a superiority complex (which IMHO is well deserved, I simply cannot wrap my head around functional programming).

    Finally, my comment about the actual talk is that TDD is all fine and good when sorting out the mess that people make with Ruby in their own applications. But when that mess is so awfully bad and has thus been baked into the API (from experience, I am looking at you ActiveRecord), there is little you can do about it. Where the language and framework require you to monkey patch, nothing will save you from those hell debugging sessions, not even TDD.

    Thanks for the link Robert, very interesting presentation.

  • http://www.smokejumperit.com Robert Fischer

    Added the video to the podcast feed.

  • http://www.smokejumperit.com Robert Fischer

    @Richard

    This post was written by Brian Hurt, the other blogger on this page. See his author page for a list of the posts he wrote, as opposed to my author page and the ones I wrote.

    @Everyone

    Clojure pretty well shows that Lisp (as a family of languages) isn’t dead. In fact, I doubt it will ever die, because it’s so obnoxiously perfect in its mapping to the theoretical underpinnings of computer science. And because it’s what emacs is programmed in, and God knows (but has little to do with) emacs is immortal.

  • http://www.smokejumperit.com Robert Fischer

    @Richard

    And no, Scala doesn’t provide a “good enough” alternative to functional programmers. If you look at the people flocking to Scala, it’s not made of up those with backgrounds in lisp, haskell, ocaml, or erlang — it’s made up of people whose backgrounds are in Java. Interestingly, you’re even seeing an outflux of attention from the JVM to the CLR, where people are looking into F#. F# is basically a more object-friendly OCaml, so for hints on why people are moving over to F#, see my Why Rubyists Should Learn OCaml, or compare the Scala versions of code to the OCaml versions of code presented in 7 Actually Useful Things You Didn’t know Static Typing Could Do: An Introduction for the Dynamic Language Enthusiast.

  • Brian

    Actually, the Lisp v. Clojure difference is exactly what James Robertson was talking about. Clojure doesn’t have the arrogance that Lisp did/does. The smalltalk community had nothing on the Lisp community for arrogance. I mean, come on- we still make jokes about the arrogance of Lisp. But by being on the JVM, and providing a close and easy mapping between Java and Clojure, Clojure is being less arrogant. It’s admitting that it needs to deal with and interoperate with the huge bodies of existing Java code. Lisp is dead, in the same sense that Cobol and Fortran are dead (both of which, I comment, still have people coding in them). But it can find new life if it sheds it’s arrogance (as Clojure).

  • http://www.smokejumperit.com Robert Fischer

    @Brian

    Who is James Robertson?

    I’m not sure Clojure is really not arrogant in that sense. Being on the JVM doesn’t solve the underlying arrogance: that comes from the mapping back to CSci ideas, and lisp developers overcompensating for the sheer volume of lay-up parenthesis jokes.

  • Brian

    I think I got the name of the guy doing the presentation wrong. Sigh. I’m terrible with names. All you humans look alike to me.

    Actually, Clojure uses fewer parens, and more other symbols, than “true” Lisp does. Granted, it has way less syntax than “normal” languages like Java, but it doesn’t take to the extreme.

    Whether Clojure can break through the wall that everyone else built around Lisp (as opposed to the wall the Lisp programmers built) remains to be seen. But I comment that in the “Programming Clojure” book (being released by the Pragmatic Programmers) has, as chapter 3, a whole chapter devoted to working with Java. I’m still a Clojure N00b, but it feels to me like Clojure is a whole lot more willing to compromise and deal with ugly problems (like legacy code) than Lisp was.

  • http://www.smokejumperit.com Robert Fischer

    To be clear, the speaker is Bob Martin of Object Mentor, a.k.a. “Uncle Bob”. He’s on Twitter at @unclebobmartin.

  • http://donsbot.wordpress.com Don Stewart

    Norman Ramsey said some things recently that I think are on the money http://stackoverflow.com/questions/822752/should-i-learn-haskell-or-f-if-i-already-know-ocaml/823338#823338 Basically, the investment in Haskell in language researchers means they’ll be Haskell papers for many years to come. When the Haskell papers no longer appear at ICFP, then we can turn off the lights.

    The other direction, though, cracking the mainstream, is really hard. People are tied to the JVM. People are tied to .NET. This hurts Python, Erlang, Haskell, Ruby. It gives free “credibility points” to Scala, Clojure, F#, Groovy.

  • http://neilbartlett.name/blog Neil Bartlett

    I don’t think the parallels hold at all, sorry.

    His point was that Ruby programmers need to be disciplined to avoid making a mess. Well, Haskell programmers have more ways (and more reliable ways) to avoid making messes than Ruby programmers do. And I’m not just thinking static typing here, but also purity, QuickCheck, HPC and so on.

  • Brian

    Neil Bartlett: Very good point. One of the advantages of Haskell is that if you start trying to create a mess, it makes your life a living hell. Keep your code clean and it’s a breeze. This is one of the reasons I like the strict static typing languages of the Haskell/Ocaml/F# variety. But note- what was his advice about keeping the code clean? Unit testing. The difference is that in Ruby/Smalltalk, unit testing is optional- in Haskell, static typing is not optional. So there is still a mapping there.

    But you are right- I was mainly thinking about the “building a wall, or having a wall built for you” aspects of the talk.

  • foo

    Haskell and Lisp are very different things. Haskell is basically a single language with a standard (in some ways similar to Common Lisp), some implementations and several experimental versions. Lisp is still a larger family of programming languages (Scheme, Common Lisp, Emacs Lisp, Logo, Clojure, …).

    As a language, Haskell and Common Lisp are also very different. It is a huge mistake to assume that Haskell is a more modern language making Lisp obsolete. It is not. Haskell is really a different language with different application domains. Lisp has not much lore to offer for the Haskell community. Lisp was invented for experimenting in poorly structured domains. Common Lisp was invented to make the result of that research deployable in the military domain (planners, expert systems, …). Common Lisp still has ten active maintained implementations, four of them commercial (LispWorks, SCL, Corman Lisp, Allegro CL). ITA Software for example currently writes the business logic of a new airline reservation system (for Air Canada) in Common Lisp.

    Lisp was not killed by the capability of Lisp programmers to create a huge mess. It was not killed at all. This capability at the same time makes a larger industry adoption (which looks for ‘industrial’ programmers that are easily replaceable and does projects where large amounts of people work in a controlled environment) of Lisp impossible AND secures the survival of Lisp, since it still supports exploratory programming in small to medium sized teams very well. The capability of creating a huge mess is somewhat a consequence of its flexibility. But if we remove that flexibility from Lisp, then we weaken its appeal in its core domains.

    Haskell people should really try to get rid of their Lisp complex. Haskell is a very different language. It will have users for a long time – at the same time really large scale adoption is unlikely, since Haskell is too complicated for most of the programmers in industry.

    Lisp is not dead, it just smells funny.

  • Pingback: Software development gems « Open game programming

  • codemonkey

    Clojure wont win the battle but may win the war. Is it better than Haskell, Smalltalk, Common Lisp or Scala? No. It’s not better, anymore than they are better than Clojure. What Clojure is, is a well thought-out, well designed language with unique features as well as features that other languages share. That said, the other languages in the list also have their unique features.

    Picking a language, as everyone must admit is a very complicated exercise. The language selected most is the one that is mandated by the organizations we work for. In the rare case where one is given the choice to select a language, macro-economics more often than not, play as important a role in selection as anything technically related.

    Now back to the first statement. In fact, Clojure may or may not win any given battle. The dynamics of a battle (a language selection) are far too specific to a given environment and problem domain to say whether it should or could win without a much deeper understanding of the particular battle situation. What I do think however, is that Clojure will win the war. In “war” I mean, it will “survive” and prosper unlike so many other languages that have fell by the way side.

    Clojure does not attempt to be everything to everyone like Scala or Common Lisp. Clojure is not as academically pure as Haskell. Clojure, if it is anything at all, is pragmatic and delivers on its targeted objectives. It will win the war (survive) because those objectives are clear, concise, achievable and most importantly understandable.

    A hammer still survives despite the introduction of the nail gun. Why? Nail guns are clearly more efficient aren’t they?. A hammer survives because, not all problem instances are of the same scale. Clojure is like the hammer. Haskell is great when the problem is purely functional. I would hazard to say that while most problems can benefit from a functional style of programming their solutions are not entirely without side effects. Somewhere in there there is a “sweat spot”. A functional side effect free line in the sand, so to speak. One could argue forever where that line is but the point is; that if your on one side of the line Clojure’s approach is a very efficient one and if your on the other Haskell might be more suitable. My observation of the commercial landscape gives the majority of the space on either side of the line to Clojure.

    With respect to Common Lisp and Small talk the battle and the wars are over. They are what they are. They have survived and will continue to do so, no doubt for many years to come, but they will not become more than what they are. This outcome is cast in stone as soon as they were standardized and relegated to the bureaucratic standards heap.

    Scala, on the other hand wants to be a better Java. Clearly its goals are to add functional capabilities to a language that was lacking them. Scala may indeed become a successful general purpose language. It is a well designed language. As a general purpose language however, it suffers from the same fate that all general purpose languages face. It is a compromise of an over-abundance of objectives. The greater the list of objectives, the more general it is, the more of a compromise it becomes. This is both a strength and a weakness.

    Comparing Scala to Clojure is more straight forward.

    Scala is great when you have general problems to solve that would generally be solved with Java but you want to use something cool and new. Scala does many things better than Java but jumping the language gap is always an expensive proposition. Is there enough value choosing Scala over Java? You would have to determine that for yourself. It is a very challenging business case to switch languages. Are the benefits of switching from Java to Scala so great and so provable that it makes conclusive sense to switch? For some perhaps, but for most large enterprises that drive the JVM stack blueprint, not likely.

    Clojure on the other hand is great when a STM capable, Dynamically typed, Homoiconic, macro leveragable language is required. While the later seems obscure, it’s not. Some problems are simply very hard, and very expensive to solve without those features. More importantly the number of problems that fit this category is growing like the dickens. These problems are at best solved, with great difficulty, with general purpose languages.

    Clojure will survive because all the other languages have made fundamental design decisions that conflict with the holistic set of features that Clojure is built upon. Sure the other languages can “do” whatever needs to be done but they aren’t as elegant as Clojure for these types of problems. The other languages are strong in most general problem domains but not especially strong in this specific problem domain. The other languages cannot simply be extended to create an optimal solution for these types of problems. Because they have fundamentally followed a different design approach they will not be optimized for problems this specific without breaking many of the other design designs that they rely upon.

    What is far more likely is that Clojure will loose to a language that has yet to be developed that finds an even better solution to the aforementioned type of problem. Until that time comes however, we have Clojure.

  • http://www.syskall.com Olivier Lalonde

    Interesting thoughts codemonkey. On a side note, it’s kind of funny that some comments are longer than the original post.

  • Brian Hurt

    I’m programming clojure as my day job, so trust me- I’m well aware of it’s benefits and drawbacks. It’s biggest benefit is also it’s biggest drawback- dynamic typing.

    I’ve decided that object orientation and static typing go together like chocolate and motor oil. The problem is that the true type of an object in an OO program depends upon where it came from, all the way back. Static typing an OO language is basically implementing a dataflow type system, in a situation where “I don’t know” isn’t an acceptable answer. Forget type inference, in this case- just specifying the types requires a complicated type system, handling (at least) both co-variance and contra-variance of types. A type system, in other words, that would be of interest to a PhD-level type theorist, but one that would be nigh onto impossible for a mere mortal (like even me) to understand.

    Given this, going pure dynamic typing is an obvious win if you’re dealing with OO at all. Clojure is the least painful way I know of to access all those huge Java libraries.

    On the other hand, dynamic typing is throwing away one of the most powerful and useful correctness tools for software we have- static typing, also known as static analysis. Having just spent half an hour of my life tracking down a bug that turned out to be that I was passing a map in where a vector of maps was expected, a bug that a decent (by which I mean Haskell/Ocaml/etc. style) type system would have caught and I would have fixed in 30 seconds.

    Having now worked, in a production setting, with both Ocaml and Clojure, given a choice between macros and static typing, I’d take static typing and I wouldn’t look back. The measure of productivity isn’t “how fast is it to write the code?”, it’s “how fast is it to get the code working?” My experience is that both me and every other programmer I’ve ever worked with spends a hell of a lot more time debugging the code than they do writing the code. Especially if you count the time it takes to design, write, and debug unit tests- which I do. Unit tests don’t add features to the product, they’re just there to find and help isolate bugs. Just like static typing.

    The big advantage of Clojure is then that it’s on the JVM and has really good integration with Java, giving you access to all those huge Java libraries- Terracotta, Lucene, Restlet, etc. This is an even bigger win in terms of productivity that either macros or static typing- if you can turn a 30K LOC project into a 5K LOC project plus a 100K LOC library that someone else has written and already debugged, that’s a huge win.

    As just a side note, Haskell does allow side effects and mutable variables. It’d be a pretty boring language if it didn’t- I/O is a side effect. Haskell just “isolates” the side effects within monads.

  • http://jimdesu.us James

    Brian,

    (Besides a great response in general,) thanks for the last Haskell note: haskell isn’t just useful for pure stuff, it just takes learning to structure your code in “burritos”.

  • http://code.google.com/p/counterclockwise/ Laurent Petit

    Hello Brian,

    Please note that, while indeed not having compilation-time type correctness analysis, clojure has introduced, since version 1.1.0, the notion of pre and post conditions, that you can place on any method. And they can be removed at runtime, depending on the value of a global flag.

    So with this feature, it’s totally possible for you to write type checks in pre-conditions, thus allowing you to minimize a debug time by having the code “fail fast and close to the error”.

    See http://clojure.org/special_forms#Special%20Forms–%28fn%20name%3F%20params*%20%20exprs*%29 for detail on the pre- post- conditions feature.

  • http://slobodanblazeski.blogspot.com/ Slobodan Blazeski

    Clojure is going nowhere until there is an it just works implementation of it. Currently there is plenty of plugins to choose from for any java ide but none of them just work. The amount of early adopters who are ready to cope with configuring and hunting through dependencies is insignificant. Until clojure is ready to cross the chasm the war is far from won.
    http://www.ericsink.com/Act_Your_Age.html

  • Michael

    If I remember correctly, Clojure supports type hints, right? Wouldn’t that support a more ‘static’ style?

  • http://enfranchisedmind.com/blog/posts/author/bhurt-aw/ Brian Hurt

    The type hints are A) slightly clunky, and B) excessively limited.

  • Pingback: Destillat #11 | duetsch.info - Open Source, Wet-, Web-, Software

  • http://blog.sidu.in/ Sidu Ponnappa

    I’m not going to get into the language wars thingum, but I must disagree with Slobodan when he says that getting started with clojure was hard. I found it ridiculously easy. 20 minutes tops.

    brew install clojure, add clojure mode to emacs, la clojure to idea or counterclockwise to eclipse and you’re ready to roll. Add leningen to your project and dependencies are a done deal.

  • http://charsequence.blogspot.com/ Shantanu Kumar

    You can guard against wrong argument types in Clojure:

    (def *assert-args* true) ; turn this false in production code

    (defn foo
    [^String x]
    (if *assert-args* (assert (string? x)))
    ..)

    ;;; while calling foo in production
    (binding [*assert-args* false]
    (foo “hello”))

    Would rather say that make this *assert-args* application-wide so that all functions in your app honour it. I am using this technique in SLRat:
    http://bitbucket.org/kumarshantanu/sqlrat/src

    A better idea may be to define assert-args like this:

    (def *assert-args* (atom false))
    (defn assert-args? [] (@*assert-args*))
    (defn toggle-assert-args []
    ..) ; toggle the value, invoke from backdoor in production

  • Ryan

    Go away.

  • Ryan

    All those huge Java libraries are utter garbage though. Nasty, multiple-inheritance cancer. You can probably rewrite most million-line Java libraries in a few thousand lines of your favourite *modern* language (ProTip: Java is NOT modern, it’s pathetic and outdated).

  • Ryan

    The JVM is a completely unacceptable dependency and adds unacceptable overhead, inflexibility and complexity. The JVM will die a slow but sure death.

  • Ryan

    Lisp is dead. Barely anyone uses it. End of story.

  • davorak

    The link to the video is unfortunately no longer working.

  • timcharper

    Dood. Have you used the joda family of libraries? How can you possibly say that they are all garbage? *scratches head*. Maybe you haven’t really used them.