“In another thirty years people will laugh at anyone who tries to invent a language without closures, just as they’ll laugh now at anyone who tries to invent a language without recursion.” — Mark Jason Dominus
You might be wondering what all of the talk about closures is about, really. You might be scratching your head at the boring examples that just run a simple little counter inside a function. You might be wondering how functional programming can be more fundamental than (and even able to subsume) object oriented programming. You might be disappointed that Mark Jason Dominus hasn’t gotten his book up on-line, yet. You might be willing to settle for a quick dumb example in Common Lisp written by an average developer. If any of the previous guesses are right, you came to the right place.
In this text file, you’ll find a mere 16 13 lines of code that define a small chunk of OOP in Common Lisp. The code should not only be understandable to beginners, but it was actually written by a beginner– so it should also hopefully give an indication of how easy it is to build “new” fundamental-ish programming concepts onto Common Lisp.
An “obi,” as I define it here, is somewhat like an object, but there are some key differences. (I call my version of an object an “obi” because I’m implementing just a very small piece of OOP.) An “obi” is a hash table wrapped up in a closure. The closure provides one of the main pillars of OOP: encapsulation. Nothing in your program can mess with the variables inside of closure without interacting through the function call that the closure provides. The hash table provides a place to store all of your properties and methods. Because Lisp is dynamically typed and because functions are first-class objects, there’s really no need to make a difference between properties and methods. In an “obi,” functions are just one of the many information types that can be stored in the hash table.
In the example below, we see an obi being used from the REPL prompt. Its color and shape properties are set and also a function called add is put in and called. The “.” is used in Common Lisp to notate a dotted list, so I used ~ to represent “get”, ~> to represent the create/set a property/method, and ~! is used to represent a call to an obi’s function:
; SLIME: The Superior Lisp Interaction Mode for Emacs
CL-USER> (setf f (create-obi))
#<COMPILED-CLOSURE CREATE-OBI-1>
CL-USER> (~> f ‘color ‘red)
RED
CL-USER> (~> f ‘shape ‘square)
SQUARE
CL-USER> (~ f ‘color)
RED
T
CL-USER> (~ f ‘shape)
SQUARE
T
CL-USER> (~> f ‘add #’+)
#<SYSTEM-FUNCTION +>
CL-USER> (~! f ‘add ‘(1 2 3 4 5 6 7))
28
Obi’s lack any form of “type”– in fact, you can add additional properties and methods to them at any time. Even if you don’t intend to use Common Lisp in a production application, this is an option that should be in your mental tool box. You may not always need to resort to using inheritance or subclassing to create a variation of an object you defined. If you think a little bit more functionally, you can abstract out the bulk of the design and then allow other developers to customize its use by setting or overriding some of the key functions. Of course, in a wide-open typeless setting, that’s a feature you get whether you think you want it or not!
For a much more elegant and substantive example of how to implement OOP in Common Lisp with an insanely small amount of code, see Paul Graham’s Ansi Common Lisp.
PS If anyone knows how to trick WordPress into letting me display Lisp code without destroying the indenting, please let me know.
PPS Looking at the search engine traffic coming in here, I see that (besides all of the people trying to figure out carriage returns in Emacs) there are a few coming to the site for stuff like “lisp closures,” “oop in lisp” and “lisp hash tutorial.” Hopefully this post will provide a little more substance for those folks than the previous drivel I’ve spewed forth here in my clumsy efforts to get used to some of these new ideas.
PPPS Please forgive the hyperbole in the title.
——————————
Related Articles: