Hacker News new | past | comments | ask | show | jobs | submit login
What learning Lisp taught me about other languages (unwashedmeme.com)
32 points by mqt on March 30, 2008 | hide | past | favorite | 37 comments



I did not like this post. Of his four insights:

* two of them are common to almost all high-level languages (Python, Ruby, and Tcl all have regular syntax that deliberately improves on C/C++, and dynamic types practically define "scripting" languages),

* one of them is spurious (Visual Studio programmers don't care how much precious memory they waste as long as Intellisense keeps working, and plenty of C programmers use vim), and

* the only insight here that has enough valence to be interesting --- on the scoping and binding rules of variables --- is covered so superficially that it's hard to tell whether the author actually understands what he's saying. You mean "learning lisp" didn't teach you enough to evaluate Python's closures, or Ruby's block/lambda idiom?

This article won't be a total loss if it prompts somebody to write a more knowledgeable and useful article on the lessons a Lisp education brings to bear on modern languages. I'd love to read that.


I'm interested in your critique but it seems to me you've misrepresented two of his points.

#2 compares Lisp's minimalism to any language with more complicated syntax, not just C/C++. So I don't think this insight is "common to almost all high-level languages". (The idiosyncracies he mentions are from Ruby and Python.)

#3 isn't about Visual Studio's memory usage, it's about it being slow [1]. When I work in C#, many times a day VS is unresponsive enough to break my flow, so much so that I go off and check a website like this one (it's better than sitting there feeling angry). This is disastrous in a programming tool, so I don't think the author is being precious.

(There's also a deeper point to be made here, which is that the ultra-interactiveness of Lisp and Smalltalk environments is so different from what one experiences in the likes of Visual Studio that it makes a qualitative difference in one's programming.)

There may even be a little more to #1 than you give him. "In Lisp it feels like types are a tool I can employ when I need it" refers not just to static-vs-dynamic typing but also to the fact that one can easily write functions without having to make up types to hang them on (i.e. programs don't have to be organized into object models). That's not true of all high-level languges.

I share your desire to read more knowledgeable and useful writing on this topic. But I did like the post because it's clearly coming from real experience.

[1] Admittedly, much of this slowness is due to the add-in bizarrely known as Resharper. But that's Visual Studio's fault too - for being so backward and provincial that it needs a humongous third-party workaround to achieve bare tolerability even compared to Java.


Addressing your points in the opposite order:

#3 may be true for C# development; I read a lot of C#, but don't write it. But I did spend 4 years writing a significant amount of systems C++ code in VC++, and --- at least 8 years ago --- VC++ was significantly better than any comparable C environment.

We can get into a tit-for-tat on it versus, e.g. GCC, but I feel like one way to lose a programming environment shoot-out is to imply that Microsoft half-asses that part of the business.

Regarding #2, you seem to be sticking up for the author's implication that Ruby has "complex" syntax compared to Lisp. Clearly, most languages have more "idiosyncracies" (here defined as: "notation of any sort") than Lisp. That doesn't make Lisp's austerity an interesting lesson to take to other languages; it is, in fact, the major failure of Lisp.

There is a notion, unaddressed in the original post but far more important than any of that post's insights, that obsessively regular syntax is crucial to metaprogramming. Even defined down to "true macros", this is simply folk wisdom: you can get "Lisp-style macros" out of any language that gives you access to an abstract syntax tree.

Finally, call the two "mainstream" high level languages Ruby and Python (relegating Perl and PHP to uh, different, uh, categories). Both share the type system the author appreciates in Lisp.


Re #3: you're right to distinguish between the MS environments for C++ and C#. Your comment on VC++ matches my experience from about the same time. But when I say that VS.NET is backward and provincial, believe me I mean it as an understatement. There are very clear points of comparison (Eclipse and IntelliJ) and compared to either of them VS is a bad joke. It only survives because the MS development world is largely a parochial backwater in which most programmers eat the porridge they're given and don't care to look at anything else, like medieval peasants who never leave their village.

Apologies for ranting. I've never been a big MS-hater (though I seem to be getting there), and I hardly think the Java IDE is the last word in programming environments (having an editor generate my duplicate code for me is not my idea of a good time; as you may have noticed, I like Lisp!) But like most hackers here, I care deeply about my tools, and it pains me to work in ways that feel suboptimal or ugly.

Your other points were, as usual, pretty interesting, but I burned myself out on this one. :)


> it is, in fact, the major failure of Lisp.

I won't even mention macros, but I'm curious as to why you think s-expressions are a failure? It's one of the things I like BEST about Lisp.


I like s-expressions too, but --- and I'm asserting this without a shred of evidence, appealing to the better angels of your common sense --- most developers, Peter Norvig notably included, believe other languages benefit from having more notation. For one thing, to a point, increasing the level of notational "richness" of a language improves comprehensibility of code.


Just curious - has Norvig said that explicitly or (like Steele and Gabriel and Weinreb and others of that generation) has he just been pragmatic?


I'm referring to Norvig's comments on Arc, which suggest more notation (albeit notation that remains isomorphic to sexps).


Where/when did Norvig comment on Arc?



I don't see much there to suggest Norvig is a big fan of adding syntax to Lisp. In fact you could read "This seemed to satisfy the infix advocates" as an expression of the opposite viewpoint.


Reasonable people could disagree, unless/until Norvig clarifies, but I'm going to take his apparent conversion to Python as evidence that Norvig is not a sexpr fanatic.


Frankly, I don't think you "get" Lisp at all. Lisp's lack of syntax is its greatest strength. Beginning or inexperienced programmers in general seem to have great difficulty with this concept.

> Even defined down to "true macros", this is simply folk wisdom: you can get "Lisp-style macros" out of any language that gives you access to an abstract syntax tree.

Here's what Norvig says about a particular language that has access to the AST (he's not a "convert" to Python - he just decided to use it for examples in his AI book because he feels beginning programmers can pick it up easier):

Python does not have macros. Python does have access to the abstract syntax tree of programs, but this is not for the faint of heart. On the plus side, the modules are easy to understand, and with five minutes and five lines of code I was able to get this:

>>> parse("2 + 2") ['eval_input', ['testlist', ['test', ['and_test', ['not_test', ['comparison', ['expr', ['xor_expr', ['and_expr', ['shift_expr', ['arith_expr', ['term', ['factor', ['power', ['atom', [2, '2']]]]], [14, '+'], ['term', ['factor', ['power', ['atom', [2, '2']]]]]]]]]]]]]]], [4, ''], [0, '']]

This was rather a disapointment to me. The Lisp parse of the equivalent expression is (+ 2 2). It seems that only a real expert would want to manipulate Python parse trees, whereas Lisp parse trees are simple for anyone to use.


Norvig didn't convert to Python, Python converted to Peter Norvig!


I agree. He's seeming to gloss over the fact that the whole point of higher level languages is that they exchange some simplicity for power.


No, the point of high-level languages is that you exchange speed for simplicity and power.


speed and simplicity are roughly interchangeable.


If that were true, we'd all be writing fast, simple programs in assembler.


You forgot the words "the illusion of".


Speaking as someone who's happiest with haskell and scheme, I have to say that what he needs to learn is that bad type/macro systems are oppressive, but good one's are amazingly powerful and expressive. (As that would be much better than simplistic types = bad but macros in general = good continuum)

The question is, how do you develop an aesthetic sense for these without say reading the research literature on both topics? I mean, it suffices to use the good examples of each for a while, pushing their strengths to the limit, but that at best gives folks a one dimensional view of the design of linguistic features, rather than a richer sense of strength, weaknesses, and tradeoffs.

As some other folks have mentioned, the other points are sort of irrelevant to the core of C#/++/java et al experience.

One point that seems to be missing is the (I think standard) point that interactively testing code by being able to interactively define or execute functions is FANTASTIC for developing, because it facilitates (IMHO) an easier process of evolving the software


I've played with Lisp a little, and I'm amazed at how many complex things such as Emacs can be built from a few simple axioms.


A few simple axioms and a whole lot of C code.


apt-cache show emacs22-el

  Installed-Size: 13080
The wonders of emacs are embodied for the most part in the most primitive Lisp dialect still in widespread use. Emacs Lisp doesn't even have lexical scoping, and it's still amazing.

Not that I have anything against C, when it's used to bootstrap a Lisp implementation, at least.


I don't get all the love for lisp. In my lisp experience I remember being in debugging hell trying to count out between 18 and 19 close-parentheses to add some parameter I'd forgotten. Bad memories.


That doesn't sound pleasant, and no one would want to work that way for long. But no one does work that way in Lisp for long. Any decent editor takes care of all that. And it's not like that fact is obscure, either! The parenthesis objection is always the first thing to come up, and the editor rejoinder is always the second... it's the ceremonial opening of The Lisp Debate.

Why do the parentheses always come up? E.g. Crockford advocating Javascript: "You get lambdas without having to balance all those parens." But balancing all those parens is easier than balancing all those parens, curly braces, square brackets, commas, and semicolons that one is used to in other languages (again, assuming a decent editor). This is so obvious to me that I wonder whether the parenthesis business is a stand-in for other things that people really don't like about Lisp. It's harder to pin those other things down so people single out Lisp's most visibly distinctive feature - parentheses - instead. (This has the bonus of being instantly convincing to the ignorant.)

I'm not saying people should like Lisp, or that if they're intelligent enough and give it enough of a try, they will like it. I know at least two brilliant programmers who meet those criteria and don't like Lisp. (Interestingly, both favor Smalltalk.) I don't know of anyone who's quite gotten to the root of why.


Most text editors have some sort of parenthesis matching highlighter. I don't usually find counting () to be that difficult. I see that the greater problem is that lisp (and a lot of languages that empower functional programming ideals), undermine the idea of lines of code that other tools like source control and debuggers take advantage of.


Could you elaborate on your experience? You very rarely hear anything bad about lisp, so it would be interesting to hear more from someone who has had a bad experience with it.

There is probably no perfect language, and every one has its good and bad sides - it would be great to hear more about the bad sides of lisp. Simply because the arguments are never heard. I'm assuming that there are bad sides of course :-)


You should watch the SICP videos, and play along with MzScheme.

Sussman has a sort of rythym when he closes parens. It was definitely a moment for me when I sort of recognised myself doing it.

I think once you have written enough functions in Lisp or Scheme, it becomes ingrained, that you sort of parens-match whilst reading back through the function.

I've only written a few thousand lines, so it doesn't take that much practice. Obviously you sort of need a real project to even make a dent in picking up a language.


if you're having that much trouble debugging paren, put them all on their own lines and use indentation. then it'll be easy enough to fix.


If he used an editor that auto-indented parens, he would probably be using an editor that had M-x forward-sexp and M-x backward-sexp too, so the debugging wouldn't be a problem.

Still, 18-19 close parens sounds excessive. The source for ourdoings.com has 1 place with 9 close parens in a row, 4 places with 8, and 7 with 7. That's in 13KLOC.


I looked and discovered you were using Jetty, does that mean you're using SISC or JScheme?



Funny, I didn't say Kawa because I've always assumed SISC was more popular... I didn't know about BRL though, thanks for the tip!


Kawa can't capture continuations, so SISC definitely gets more attention. However, Kawa is way faster. If you read SISC's performance boasting you'll notice that it only compares itself to other Scheme interpreters on the JVM. Kawa is a compiler.


Given that this guy's main complaint with C#/.NET (as opposed to VS) is essentially that it allows the designer of a library to enforce hiding of the implementation (see http://ryepup.unwashedmeme.com/blog/2008/02/13/brief-list-of...) I'm not sure the rest is worth taking seriously.


That's not his main complaint at all. His complaint is that C#/.NET inhibits him from building abstractions natural to his problem. He gives three good examples of this, obviously drawn from real experience working on real problems. He also gives good examples of the kind of workarounds one is forced into when blocked by a language or library from growing one's own program in a sensible way.

I'll add that, in my experience, most claims about programming that talk about "enforcing" are rooted in theories or processes about programming that bear little relation to what hackers actually do.


That's one way of interpreting it. But it does seem that what he felt was natural was to override methods marked as "do not override" and access members marked "private" or "protected".

Does your experience include creating a public binary API and shipping multiple versions of it? Just asking.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: