In my last post I mentioned reading Practical Common Lisp. I went on through several more chapters since I wrote that (quite a few more) and one practically made me stop. The first “practical” exercise is writing a library that makes it less horrifically painful to use Common Lisp to deal with reading directories.
It was a pretty quick little library and I’m sure effective, but at that time, I was kind of tired of hearing explanations of how “this has a meaningless name, for historical reasons,” or “this is completely contrary to how you’d expect it to be considering other parts of the language” or whatever. There’s a lot to just get used to in Common Lisp. Seeing an entire “practical” chapter devoted to creating a library to fix kludgy implementation problems stemming from Common Lisp’s advanced age was offputting.
But then I realized that a little ahead were the chapters on CLOS, the Common Lisp Object System, something I had always wanted to understand and never quite got. I didn’t really understand how Object-Oriented systems based on multi-method dispatch worked.
It was a really good explanation. I think I understand it now. One point that was made was that it is not a “message-passing” type of OO, the way Smalltalk and Ruby are. I realized that while CLOS is pretty cool, I really like the message-passing style of OO. It made me wistful for Ruby.
But CLOS is way powerful, and the book had a great explanation of it. Now if I take a look at other multi-method-dispatch systems I’ll have a better context from which to understand them.
The chapter on LOOP-fu was interesting. LOOP is a mini-language implemented with macros within common lisp that lets you write Python-like loop constructs (probably more powerful than Python’s loops) in a not-very-Lispy notation. It made me think Python might have been influenced by Common Lisp LOOPs.
I also wanted to check out the chapter on packages, because that was a big part of Common Lisp I didn’t previously understand. Turns out they’re a lot like Perl, but that it’s easier to shoot yourself in the foot using them than with Perl.
I still haven’t read most of the “practical” chapters yet. (I skipped forward to get to some of what I considered the good stuff.) But overall it didn’t make me want like crazy to program in Common Lisp. It made me feel like I could if I wanted to for some reason. It cleared up a lot of what was mysterious to me about Common Lisp. The only thing that Common Lisp has that I really desperately wish I had in other languages is its glorious macro system. I have a feeling that in terms of the “defining new syntax structures by being able to take unevaluated code chunks” aspect of macros, you can get a lot of mileage out of Ruby’s blocks for doing macro-like things. However, macros can do a lot more than that.
Overall it made me think fondly of Ruby, because Ruby uses a style of object orientation that seems more natural/intuitive to me, and can do a lot of (though by no means all) the spiff stuff Lisp can do.
It also made me think fondly of Scheme, because Scheme is a lot less ass-ugly than Common Lisp, and can do a lot of the same good stuff, though it doesn’t have even a tiny fraction of the built-in cool stuff in the standard.
It definitely made me open to using Common Lisp if I ever think of a project where it would come in really handy. And I do plan to finish the book when I get a chance.
Fun Fact about Common Lisp: standard Common Lisp has no networking libraries at all, but it does have a built in function to print integers as Roman numerals — using either the new style (14=XIV) or the old-style (14=XIIII) Roman numerals. Huh.
8 thoughts on “Thoughts Reading Practical Common Lisp”
Fun fact about C: standard C has no networking libraries at all, but it does have a built in function to print . Huh.
Didn’t seem to
I’m sorry some of your comment got lost, Robert! I’d be interested to hear what you have to say if you care to repost it. (I wish I knew why that happened.)
Touche’. I guess Common Lisp just has so *much* built in, the bits you might wish were there that aren’t stand out more. Whereas standard C is… well… it doesn’t raise your expectations the same way Common Lisp does. ;)
If you don’t like CLOS, you can do like many other people have done and use macros to define your own object system, based on whatever model you want. It will work just as well as CLOS, because CLOS was originally just a set of macros written in Common Lisp, until it got incorporated into the standard.
Once you’ve done a project in Common Lisp, you might try Paul Graham’s On Lisp (www.paulgraham.com/onlisp.html); most of it is devoted to extremely mind-blowing yet mostly practical uses of macros.
You’re right, macros are something Lisp has over all other languages, and they’re why Lisp has survived for so long. Whenever something new comes along (e.g. object-orientedness) Lisp just incorporates it through macros (as with CLOS). Furthermore, if another language did have an equivalent macro facility, it would pretty much be a dialect of Lisp. This is because to write macros, you need your code to be very closely reflective of the abstract syntax, because macros work on abstract syntax trees (parse trees) and generate other parse trees. And Lisp is basically (with certain exceptions) just notation for parse trees.
Incidentally, Lisp also lets you define new concrete syntax with read-macros. You could, for example, define syntax so that #[2 7] meant the list of integers from 2 to 7.
Thanks for the comment, Elliot.
Yes, the fact that Lisp syntax and Lisp data structures are mirror images of each other seems to be the terribly important thing that allows macros to have the power they have.
The only not-lispy language I’ve heard of that might have something comparable is REBOL; I don’t know much about REBOL and so I don’t know how comparable code-as-data in REBOL is to code-as-data in LISP.
I’ve read most of Practical Common Lisp like you and I’ve quite enjoyed it.
I thought that CLOS was really cool – generic functions and multiple dispatch appeal to me.
I think I’ve pretty much gotten past the parentheses and the car and cdr crap, but I still have doubts about using Common Lisp on a project, because of the lack of libraries and all the different incompatible implementations. It seems to me that Python and Ruby have most of the power of Lisp (macros are something in which Lisp definitely has an edge) and have excellent libraries that work the same across all platforms.
The Roman numeral printer is my fault. It was more for humor value than anything else, although there are actually times when it’s useful to print Roman numerals (section/chapter numbering). The “old-style Roman numerals” was because Tom Knight asked me to put it in; that’s really pointless!
Pointless maybe but cool. I’m honored you dropped by to comment on it, Daniel! Thanks!
It seems that the standard is the real curse with common lisp. Its not going to adapt to the world moving forward and leads to multiple subtly incompatible implementations. Then once you’re outside the standard (sockets, threading, IPC etc) things diverge wildly.
I’m working through Practical Common Lisp because I’ve put off learning this great and venerable language for too long. Preferring OSS implementations leads to an interesting choice that a newcomer to the language isn’t well placed to make. I want native threads and portability. Currently learning on SBCL, I can see myself switching to OpenMCL if/when the x86 port is complete.
That’s for CL anyways – I’m interested in Clojure as a modern Lisp thats portable (in the sense java bytecode is portable), threaded and solves the library problem (java classes are trivial to call from it and vice versa). Perhaps it lets go of some of the CL baggage, but until I learn CL properly I won’t know if that’s the case :)
Comments are closed.