Atlas · Details
Scheming Is Believing
Author’s note
This is one of my worst ever. It needs at least 50% cut, possibly as high as 100%. I'm keeping all my essays here for historical honesty, even the ones I don't like anymore. But whew, yeah. I've done better.
AI Notes
Framed as a confession: Steve had spent thirteen years walking around Lisp the way most working programmers do — odd parens, no jobs, an indoor sport for graduate students — and the essay is the account of Lisp catching up to him anyway during a year-long language tour. What changed his mind wasn't expressiveness, the gift a language gives you on the small scale (Ruby and Python have plenty). It was adaptability — macros, reader macros, a working metaprogramming layer, the ability to grow new syntax inside the language for the problem you actually have. Steve sets up the EQ-slider metaphor — every language design is a set of conflicting trade-offs — and names the slider most languages don't have at all: the one that lets you move the other sliders. Lisp has it. Java and C++ don't. Perl half-has it and is paying for the way it half-has it.
The cleanest first statement of what becomes Steve's defining argument of 2005–2006: at the scale of a real codebase over a real decade, the only language axis that matters is whether the language can grow with you when the unplanned-for requirements arrive. The tour-de-Babel essays survey the field; Scheming Is Believing is the moment in the survey where Steve quietly puts his money down.
Related listings
-
2006
Lisp is Not an Acceptable Lisp
A year later, with conversion complete, Steve turns the argument inward at the Lisp community itself. Scheming is the welcome at the door; Acceptable Lisp is what he says after he's moved in.
-
2005
Tin Foil Hats
A few weeks later — the same conversion expressed as a thought experiment. Tin Foil Hats is the reasoning that produced the verdict here.
-
2005
Choosing Languages
Companion piece. Choosing Languages is the survey; Scheming is the moment in the survey where Steve himself chooses.
From the peanut gallery
Read the rest of the thread · 4 more
-
"Compiler macro" actually means something specific in Common Lisp (see the second paragraph):
http://olympus.het.brown.edu/doc/gclinfo-html/gcl_3.html#SEC190
What you refer to as compiler macros are normally called "macros" without special qualifications. You can probably safely call them "interpreter macros".
Didn't we actually compile our early C code with a C++ compiler, to get better typechecking?
-
You don't understand? Well, I'm taking advantage of a hypothetical framework for extending English in fundamental ways. Unbeknownst to you, "kuzl" is part of a new grammatical construct that makes expressing recursive ideas much more natural.
I have heard enough smart people describe the profundity of their experiences with LISP to believe that it's a lot more awesome than I currently realize. But when the selling point is how radically you can redefine the language, I feel like they miss the value of language consistency, which translates into being able to read foreign code and know what the hell is going on.
In your first Java example, you wrote one line of code, and with that alone you were able to explain exactly what Java does to evaluate that line. Any experienced Java programmer in the world would be able to tell you the same thing, just by looking at that one line.
Now pretend that you're up at 2AM trying to debug some system that you just inherited, the guy who wrote it is no longer with the company, you know he's a smart guy but sometimes too clever for his own good. And you have somehow localized the problem to this line:
(make-it-happen (widget-functor asin) (map make-it-happen data))
I don't know enough crazy things you can do with LISP to come up with a plausible example, but you get the idea. How much other code will you have to read to even discover what *sort* of thing this does?
I believe there is value in language consistency, namely that it makes it very transparent what your code is actually doing. Not that you necessarily understand *why* it's doing what it's doing, but you at least know *what* it's doing.
If LISP really gives you the expressive power to implement Perl with LISP macros, then I hardly see how it could be consistent enough to allow a large group of people to share/maintain LISP code. Unless you restrain yourself from making these deep extensions to the language, but then why waste your time writing clunky things like (setq x 1) when you could just write x = 1?
-
Daniel — I've been mostly using Kawa, a Scheme for the JVM that compiles to bytecodes, although I wouldn't really recommend it. It's not a full Scheme implementation yet — e.g. continuations are upward-only, and it has an incomplete set of SRFIs, and lots of bugs in general.
Kawa's got a lot of long-term potential, but it's not useful for production-quality work in either Java or Scheme.
I looked at the info pages for MIT Scheme recently, and they've implemented a LOT of features from other languages — e.g. list comprehensions like Haskell's.
For commercial implementations, Chez Scheme is allegedly the best. Fast, complete, portable, and actively developed.
All the Schemes implement a different feature set, and the code from one doesn't always run immediately on another. This is a serious problem with Scheme in general, and I believe it currently renders Scheme unsuitable for production work.
But I'm gradually working on figuring out if any of them is promising enough to try to work with.
-
In response to Josh Haberman's comment about considering this line of code:
What would you do if you were staring at this line of code:
if ( (*self->mark_funcs[d])(self, changed_field_number) != SUCCESS) return FAILURE;
{pointer to actual Amazon function containing this code}
...trying to figure out why the tax was computed incorrectly! My point is that any language can be obfuscated and it seems to be pretty popular in both perl and C.
Steve - I completely agree that lisp's macro system sets it apart and gives the language more power. Also, I like the fact that scheme is so "light-weight" because it comes with a tiny library.
However, big bulky libraries are also power. It can become difficult to integrate many different libraries into your application if they have over-lapping problem domains (with different implementations). So, Common Lisp is very nice in the fact that many common functions are already available to you.
Of course small vs big libraries is a problem with any language.
So, when is the Scheme Codigo implementation going to be ready?
Which Scheme environment have you been using? I've been playing around with a couple of them. PLTScheme, Scheme48/scsh and SISC appear to be the more complete ones I've found so far.
— Daniel C · February 8, 2005 12:03 AM
Josh: I put a comment here that tried to do some more explaining. Then I re-read my entry, and I see now that I'd just be repeating myself.
I don't think it's possible to be convinced of the benefits of Lisp by reading about it, or by tinkering a little with it. You just have to do a bunch of it. Lots. Tons. Then eventually it clicks. That's why I called this blog "Scheming is Believing."
So if my explanations weren't compelling, and I seriously doubt they were, then don't sweat it. It's just a blog.
— Steve Yegge · February 8, 2005 12:25 AM