Table of Contents
#+Title Just another Love Song: Common Lisp in 2017
Introduction
One of my favorite programming essays is Peter Norvig's Teach Yourself Programming in Ten Years.
I first encountered Common Lisp in the early 1990's. I'd been using AutoLisp to enhance my CAD jockeying – I'd taken up CAD as a way to get my hands on AutoCad to get my hands on AutoLisp. In the pre-commercial internet era, obtaining programming languages was non-trivial and required buying floppy disks in a shrink-wrapped box and there was no Borland Common Lisp. One day I broke down and purchased a thin and relatively expensive book, Common Lisp & Artificial Intelligence. I learned that AutoLisp was not full featured the first time I typed some interesting code…it might have involved macros and AutoLisp does not have them.
In 2012, after a couple of decades pursuing architecture, I came back to Common Lisp. I googled and wound up downloading LispIDE from DaanSystems…in part because it looked simple and in part because I was on Windows and in part because Emacs looked scary compared to an IDE, but mostly because I didn't know any better (in the sense of inexperience rather than incorrectness). I chose Clozure Common Lisp based on similar criteria.
Sometime in that June, I ordered a used copy of Graham's ANSI Common Lisp off of Amazon (Amazon was better for used books in those days and less good at video downloads than it is today). I picked it because 'Hacker News' (and that's probably why I got part of the reason why I got back into Common Lisp). Once again I was reminded that Common Lisp is not AutoLisp. It's big and complex and computer sciencey (as are pretty much all programming languages). How much did I have to learn? This example on page eleven:
> (list 'my (+ 2 1) "Sons") (MY 3 "Sons")
Caused me to write this marginalia [kindly, remember that AutoLisp did not have macros]:
Ok. So to grok this in its fullness the output of (list) is a function MY & the arguments 3 & "Sons"
At some point I installed LispCabinet. LispIDE was returning horrible error messages and throwing me into a debugger and exiting was done with numbers None of it looked like VisualStudio Express – I did not know that that's how Common Lisp worked. It turns out that error messages in LispCabinet were even worse because they were the same and I was in Emacs. To describe it as frustrating is accurate. But the silver lining was that LispCabinet was my introduction to Emacs and I could kind of see it's power (and in 2013 I took Dan Grossman's Programing Languages course at Coursera because it used Emacs).
Sometime in the next few months I had an idea for a project and decided to try Racket because it is Easy-to-Use™. Downloaded and spun DrRacket up and wrote some struct=s and ran into immutability. The error messages were lucid but WTF?. Reckoned I'd just read Racket's [[https://docs.racket-lang.org/reference/define-struct.html?q=struct#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._struct%29%29][Easy-to-Use™]] documentation for =struct
. Eventually I figured out how to use mutable struct
's and moved forward kept until I felt like I needed mutabable lists. It was a natural stopping point. I looked at Clojure. Clojure is like Common Lisp in at least one very meaningful way. It was designed for working programmers and has the error messages to prove it. It's like Racket in that it's not easy to whip out imperative code.
In April or May of 2013 I learn that come August Coursera will run a class in Racket based on How to Design Programs and taught by Gregor Kiczales. The first run of Introduction to Systematic Program Design was awesome, MOOC's were hot and new and shiney, Kiczales was thoughtful and intellegent and there was a mix of people from around the world and incredible programmers among them…and in those days Coursera was much less a paid platform. Videos are avialable here.
At some point I came up with the idea of learning Common Lisp eventually – after I had a better understanding of programming and Racket I would have enough background for it and Clojure There's a 2014 diversion into Clojure via The Joy of Clojure wherin I try to do an Algorithms MOOC in Clojure but settle upon Racket. There's a 2015 diversion into ClojureScript which I realize there's no avoiding JavaScript.
Somewhere along in 2016 I read a credible opinion that Peter Norvig's Paradigms of Artificial Intelligence: Case Studies in Common Lisp is one of the best books on programming. At the time I was thinking about applying to the Recurse Center for Winter, 2017. Being bookish and unimaginative I decided that working through it would be the basis for my time there. I didn't get in, but I carried on anyway, and that's how I wound up learning Common Lisp in 2017.
An RTFM Language
There's good news and bad news.
Googling up blogs and tutorials and questions on StackOverflow works pretty well for some languages like Python and Javascript. Common Lisp is probably not one of them (though I recognize the irony that this text might suggest). In part by the historical necessities of the pre-internet age and in part by historical accident that Common Lisp was primarily designed for professional programmers and not students (Scheme wound up filling part of that role), learning Common Lisp involves reading material that is designed for professional programmers. There are introductory resources like Land of Lisp, but most material is at the "here are some compiler directives" level of engagement.
Fortunately, Common Lisp is a standard and a description of the language is available online: Common Lisp: The Language (2nd Edition)
Symbols, Packages, 'Packages', and Systems
This section will go into terminology regarding multiple file organization in Common Lisp because it is a bit disorienting.
Symbols and Packages
Symbols
In Common Lisp a symbol is not just a name. A symbol is a compound data structure. It might be useful to think about a symbol as the name of a pointer to a data structure…sometimes I think it is useful to think about everything in Common Lisp as a pointer.
A symbol may be interned or uninterned. An interned symbol is interned because it is interned in a package.
Packages
A package is a compound data structure that contains symbols.
Packages are collections of symbols that serve as namespaces. The parser recognizes symbols by looking up character sequences in the current package.
'Packages' and Systems
The Lisp Machine
This section will go into the idea of Common Lisp as a way of using a computer rather than a way of programming a computer.
An abstraction over Von Neumann Architecture
Opinions
There are many possible permutations of Common Lisp environments [something like O(n!)
I think]. This is my snowflake opinion, not for the sake of argument, but for the sake of swimming downstream in the middle of the channel. It is premised on using open source tooling (i.e. not spending any money).
There are legitimate reasons to use commercial implementations. There might be legitemate reasons to make choices other than those I describe, but they will tend to increase the probability of swimming against the current.
The tl;dr is choosing projects that are mature, robust, well maintained, and in widespread use by experienced Common Lisp users because such project help promote a common vocabulary and common frame of reference.
SBCL
There are two good reasons for using SBCL [Steel Bank Common Lisp]. t is the most straight forward from an open source perspective.
~/common-lisp
Just put your files there like an *nix'er.
ASDF
ASDF does one thing.
(in-package :kludgecode) (def use-system (system-keyword) "Loads a system if locally available, otherwise trys to fetch it via quicklisp" (if (asdf:system-registered-p system-keyword) (progn (asdf:load-system system-keyword) 'asdf-loaded) (progn (ql:quickload system-keyword) 'quickloaded)))
Quicklisp
Installation
Quicklisp is a package manager for common Lisp available at https://www.quicklisp.org/beta/.
mkdir ~/common-lisp/quicklisp-install cd ~/common-lisp/quicklisp-install curl -O https://beta.quicklisp.org/quicklisp.lisp curl -O https://beta.quicklisp.org/quicklisp.lisp.asc gpg --verify quicklisp.lisp.asc quicklisp.lisp
sbcl --load quicklisp.lisp
System Repository
Emacs
There are two good reasons for using Emacs as the environment for developing Common Lisp:
- It is pretty much the standard alternative to commerical tools.
- Emacs Lisp allows building tools to make your life easier, and while Emacs Lisp is not Common Lisp, it's still loveable (as are all lisps).
Testing
lisp-unit
As the name implies, lisp-uint
is an Xunit inspired unit testing framework.
It should be installed using quicklisp
:
(ql:quickload :lisp-unit)
Basic documentation is on github: https://github.com/OdonataResearchLLC/lisp-unit/wiki
Other Lisps
Signposts - Finding the Right Lisp
Finding the right Lisp because Common Lisp is not necessarily the right lisp for you.
- Racket for newbies and students and SICP.
- Emacs Lisp for a practical reason to learn lisp
- Clojure -> Clojure from the ground up
- SBCL in Bash