Tim Bray has been learning up on Ruby lately, and his comparison of it with the Lisp tradition is too tempting not to respond to:
... as I would have been if I didn't pre-empt it here, every MIT undergrad was doing this kind of thing in Lisp by 1970, isn’t it quaint that the world is catching up, etc etc.
And they’d have a point; but Python and Ruby seem to have oozed further into the mainstream than Lisp ever has.
“Why?†is an interesting question, and I think the biggest single piece of the answer is inheritance from Perl’s culture of ruthless practicality. In other words, not afraid to use syntax to make the point; things are generally lists, except when they’re not; attention to typographic values; building hashes and regexes into the language; not requiring you to ever say “lambdaâ€. Any more?
I'll agree with some of those. Using "lambda" to mean "function" has probably turned a lot of people off Lisp. It's shame they didn't get over that geeky pleasure earlier.
Building dictionaries into the language is a big step that's easy to underestimate: so many things are easily and efficiently done using that data structure.
I don't know what "not afraid to use syntax to make the point" means, nor "things are generally lists, except when they're not." Is there some oblique reference here that I don't get?
Of Tim's notes, the one difference between Lisp and the current crop of dynamic languages that's really critical in my opinion is "attention to typographic values." Ruby, Python, and Perl, to different degrees, are fun to read and write because they're fairly "concrete," in the artistic sense: the code looks like things.
It's a curious fact about Lisp that it originally had an infix notation with more ordinary symbols—the so-called M-expressions—but the abstract, parenthesis-heavy syntax (S-expressions (I use it in my prose (sometimes))) was more popular in that community, apparently because it was more susceptible to macros and meta-programming.
The vast majority of developments in the functional-programming world, after Lisp, have returned to more concrete syntax, and greater typographic values. ML and Haskell allow you to define an infix operator out of nearly any string of symbols, and library writers use this facility, though modestly. Matrix arithmetic is made easy to read, for example, by using mnemonic infix symbols for the relevant operations. Arrow-like operators are nice mnemonics for I/O, for piping data from producer to consumer, and for table lookups.
On a higher level, Tim's analysis is a little lax: I don't think typographical values are part of Perl's "ruthless practicality." They're a stylistic trait that might have been thought of as experimental at first, but which panned out in the end. Language design is an endless process of evolution: of failed experiments and surprising developments that come from breeding with your perverse distant relatives. Perl injected a load of interesting new genetic material and Ruby is the descendant that's optimized it.
Sometimes, outre language communities like the functional community (think Lisp) are dismissed because of impracticality; but these communities develop in isolation for a while and come up with interesting features, which are later able to breed back in to other languages. An excellent example of this is the fact that Perl, Python and Ruby all have variants on Lisp's map
and filter
, which "mainstream" languages like C, C++, and Java had completely ignored. I see it less that Ruby succeeds where Lisp failed to become popular, and more that these island communities are presently interbreeding after a period of independent development.