December 03, 2005
Ruby As An Acceptable LISP
Eric Kidd writes the inevitable “Why Ruby is an acceptable LISP”, concluding that “Ruby is a denser functional language than Lisp” and “Ruby gives you about 80% of what you want from macros.” [via reddit, where 6 of 25 stories on this morning's front page are Lisp-related.]
The comparison is both narrow and shallow, but I think he makes some valid points and shouldn't be dismissed too quickly.
Now, given a choice between a powerful language, and popular language, it may make excellent sense to pick the powerful one. But if the difference in power is minor, being popular has all sorts of nice advantages. In 2005, I’d think long and hard before choosing LISP over Ruby. I’d probably only do it if I needed optimized code, or macros which acted as full-fledged compilers.
I don't find it implausible that for many people, doing certain kinds of work, Ruby is a better Lisp than Lisp. For others, it won't come close.
Posted by jjwiseman at December 03, 2005 11:32 AM
I decided to go with Ruby. Here's why: Without knowing any Ruby, I used one piece of documentation (the Pickaxe book) and one download, and built a multi-threaded server running in less than half a day of skimming the pickaxe book.
People keep mentioning that Lisp is evolvable. This is only true for some things. Like the above example, threading and sockets, you're going to have to rely on some lower level stuff.
Things in Ruby seem more uniform and a good guess will usually get you close. There is no guessing in Common Lisp: you're just going to have to mentally map the weird names to meaningful relationships in your brain.
I'm not trying to hate. There's things about Lisp that I really like, and I can't help but question my choice now and then for the current project I'm working on. Both languages inspire passion within their communities. Couldn't all the separate implementations just get along?
I played with Ruby for a couple of years before moving on to Common Lisp. IMHO Ruby is a lot of fun and one of the nicer languages I've used. Still, in the end Ruby started to bug me in a number of areas:
- Too much syntax, I found Ruby nearly as bad as Perl for remembering what the one/two character operators do after a few months out of mind.
- Needing to drop all the way down to C for performance and then hoping users of your code have a working C compiler.
- Too much runtime manipulation of classes and objects which makes some code hard to follow.
- No SLIME!
don't get me wrong: I'm a true believer in the mother of all languages, and I love it. But Ruby actually seems to have a chance.
jjwiseman, I'll happily grant that my comparison is both "narrow and shallow", though I would have personally preferred a different phrasing. :-)
To do LISP justice would require an entire book, and many of the arguments would be subtle. Like any profound language, LISP takes years to appreciate.
And I absolutely agree that Ruby is unsuitable for certain classes of LISP projects. You'd have to be out of your mind, for example, to try and write the Orbitz fare analyzer in Ruby. Runtime metaclass hackery comes at an undeniable cost in performance, and you can't fix it.
But like a lot of people, I seriously underestimated what can be done in Ruby. It's just good enough that the whole "Worse is Better" phenomenon needs to be on radar again, at least for people considering new commercial projects. As noted above, I think the correct answer comes down to performance, and the specific kinds of macrology you need.
Frankly, I don't understand all the attention to Ruby (other than the fact that Rails was written in it). Ruby was inspired by Smalltalk and Lisp. Why not just skip it and go right to the originals? What is Smalltalk or Lisp lacking that Ruby advances?
I don't find Ruby objectionable, but I wouldn't use it for my line of work. However, I agree that the arguments seem "narrow and shallow". The one that had me saying "Come on --seriously?" was
But there's an interesting special case in Ruby which saves us even more typing.
I just can't find that compelling at any level.
Eric, why must "meta class hackery" come at the cost of having a fully interpreted language like Ruby? I'm sure you could extract the info you need and generate the classes/code, and have the lisp system compile them just fine.
I was a Ruby fan some years ago, but I decided that Ruby was maybe on the wrong path since many of my questions began to be more on the level "i want to do this, what is the syntax for doing stuff that way?". What first felt so natural ended up being not so natural.
And I'm not all too sure about multiple inheritance being evil. It's a tool, just like goto is.
In my experience, programmers follow the path of least resistance: If a construct looks ugly or verbose, they won't use it as often. If you want a language to favor a certain style, you need to make that style look clean.
For example, Scheme supports lazy evaluation (using PROMISE and FORCE), but you'll almost never see it used in production code. Haskell makes lazy evaluation transparent, and it's actively used in nearly all Haskell programs.
So in my mind, arguments about syntax are ultimately arguments about which semantics to prefer. And since I strongly prefer functional semantics over hand-rolled loops, I like concise lambdas.
Will Ruby get macros? Apparently Matz is of the "they can be dangerous" school.
I think Ruby's marvelous, but my two feet-dragging are the lack of true macros, and the performance issue.
Kudos to Ruby for all the rest, including continuations. Nice!
Tom, as far as I know, you could implement nearly all the cool features of any major Ruby framework using macros.
LFoD, Ruby isn't going to get real macros unless somebody does something really compelling with ParseTree. (ParseTree uses undocumented interpreter features to extract s-expressions at runtime; see the link upthread. Ask me if you need a good implementation of destructuring bind for pulling those s-expressions apart.)
Matz is not particularly a fan of macros, and since Ruby is already halfway there, he has little to gain by supporting them. On the other hand, Ruby culture is much more forgiving of alarming hacks than Python culture, so who knows what the future will hold?
You can do everything you did in Lisp, too. Instead of the Pickaxe, get Practical Common Lisp (http://www.gigamonkeys.com/book). Then install Lispbox (also available at the same URL). Bam, you've got a working Lisp installation, a Lisp IDE (in the form of SLIME), a tutorial, an on-line reference, and you're all set.
"You can do everything you did in Lisp, too. Instead of the Pickaxe, get Practical Common Lisp"
That's the point: Practical Common Lisp doesn't mention Threads or Sockets. The implementation I used (LispBox for Windows using clisp) doesn't have threads, and the documentation for sockets is poor (have people sworn off examples in technical documents?).
Last time I checked, rails had only a few thousand
lines of ruby, so it ought to be not that difficult
to write something similar in lisp. Still, it don't
think it will ever be done. What is this telling
us about Lisp and its community?
CLISP is generally what people start learning lisp with since it is free and sets up nicely with emacs/slime.
But once you start looking for threads, distribution (as exes) and gui stuff you find it lacking.
For that reason I recommend people to try lispworks or corman lisp once they want to start doing stuff.
Then when you compare ruby or python to allegro, lispworks or corman lisp, you find that a lot of the things that were missing are not.
Ignorant Bystander, what Ruby has which Lisp and Smalltalk both lack is a cohesive community.
I'd love to use Lisp for a large upcoming project, but for various (valid, I think) reasons I don't want to use the commercial Lisp implementations. But the free ones are so deeply flawed when it comes to cross-platform support, threads, full-featured standard libraries and integration with non-Lisp 3rd party libraries that I find myself thinking that another language may be the better way.
Justin: When you compare Ruby to Python to Allegro or Lispworks, you still find one important thing is missing, It's not free for closed-source/commercial use.
So you have to:
- Write app for CLISP without GUI/Threading.
- Pay thounsands of dollars to use Allegro/Lispworks
- Use Ruby or Python and pay nothing.
Ignorant Bystander: Most mainstream languages are also inspired by Algol. That doesn't mean we should skip it all and use Algol instead. Just because X was inspired by Y doesn't mean Y is superior to X. Improvement is possible.
Steve: Squeak seems to have a pretty solid community, and a lot of interesting projects (including some that advance the language itself, like Traits).
Pisin Bootvong: Yes I really can't argue with you the price point... Ruby is offering for free the multithreading, not sure about the GUI?
The question is how many worthwhile commercial projects cannot afford a thousand dollar registration fee for development tools.
Justin, except that Ruby's multithreading isn't native threading. Is it really much different from event based "threading" you can use in cmucl and others?
Tom: Sorry I'm not a Ruby programmer and I guessed from the earlier poster that it had real multithreading. So I guess the commercial lisps do mostly offer full featured libraries, native multithreading, compilation etc... so Ruby only really competes on price.
I'm learning Lisp now and finding it to be incredibly powerful and expressive, although somewhat ugly to someone whose eyes are accustomed to the Algol-ish languages like C/C++/Java/etc. And aesthetics count for something. Though perhaps in time I will learn to appreciate the aesthetics of Lisp.
Ruby has the aesthetics for me and some but not all of the power of Lisp. Another area where it's lacking is in IDE. SLIME is absolutely fabulous and all the Ruby modes that I've seen for Emacs pale in comparision. Is there anything comparable to SLIME in the Ruby world?
I figure I'm getting old and I need one good language to think in. I've been doing C++ at an average level for years, but I'm really much more inclined towards the functional style. Haskell or F# fit the bill, but LISP and Slime seem great.
I just finished my first tiny Lisp program, which looks up a mysql db and renames a bunch of mpg files according to the info in the database, so that covers bits of the sql access layer, shared libs, filehandling, lists, iteration, variables.
So far, the most rewarding bit was writing a lambda to allow sort to sort a list of pathnames. It was easier, even barely knowing Lisp, than doing it in C++, and trying to wrestle functor objects etc into submission.