5882653249ed

Typos, more
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Wed, 15 Aug 2018 16:24:26 +0000
parents 61af4332b802
children 252468e5ebf0
branches/tags (none)
files content/blog/2018/08/a-road-to-common-lisp.markdown

Changes

--- a/content/blog/2018/08/a-road-to-common-lisp.markdown	Wed Aug 15 04:50:36 2018 +0000
+++ b/content/blog/2018/08/a-road-to-common-lisp.markdown	Wed Aug 15 16:24:26 2018 +0000
@@ -7,19 +7,18 @@
 +++
 
 I've gotten a bunch of emails asking for advice on how to learn Common Lisp in
-the present day (currently 2018 as I'm writing this).  I decided to write down
-all the advice I've been giving through email and social media posts in the
-hopes that someone might find it useful.
+the present day.  I decided to write down all the advice I've been giving
+through email and social media posts in the hopes that someone might find it
+useful.
 
 <div id="toc"></div>
 
 ## Context
 
 I think it's important to have a sense of where Common Lisp came from and what
-kind of a language it is before you start learning it.  There are a lot of
-things that will seem very strange if you're coming straight from modern
-languages, but will make a lot more sense if you've got a bit of background
-context.
+kind of a language it is before you start learning it.  There are some things
+that will seem very strange if you're coming straight from modern languages,
+but will make more sense if you've got a bit of background context.
 
 ### History
 
@@ -61,12 +60,13 @@
 Common Lisp.
 
 While the committee worked on the standardization process, in 1990 the second
-edition of Common Lisp: the Language was published.  This was more comprehensive
-and contained some of the things the committee was working on (see the
-comp.lang.lisp FAQ linked above for more on this).  At this point the Lisp
-family of languages had over 30 years of experience and history to draw upon.
-For comparison: Python (a "modern" language many people think of as also being
-"kind of old") [was released][python] for the first time the following year.
+edition of Common Lisp: the Language was published.  This was more
+comprehensive and contained some of the things the committee was working on
+(see the comp.lang.lisp FAQ linked above for more on this).  At this point the
+Lisp family of languages had over thirty years of experience and history to
+draw upon.  For comparison: Python (a "modern" language many people think of as
+also being "kind of old") [was released][python] for the first time the
+following year.
 
 In 1992 the X3J13 committee published the first draft of the new Common Lisp
 ANSI standard for public review (see Pitman's paper).  The draft was approved in
@@ -82,28 +82,29 @@
 
 ### Consequences
 
-So why am I telling you all this?  Because I want you to know what you're
-getting yourself into.  I want you to realize that Common Lisp is a stable,
-large, practical, extensible, ugly language.  Understanding these
-characteristics will make a lot of things make more sense as you learn the
-language.
+I wanted to give you a quick overview of the history of Common Lisp because I
+want you to know what you're getting yourself into.  I want you to realize that
+Common Lisp is a stable, large, practical, extensible, ugly language.
+Understanding these characteristics will make a lot of things make more sense
+as you learn the language, and I want to talk a little bit more about each of
+them before I start offering recommendations.
 
 #### Escaping the Hamster Wheel of Backwards Incompatibility
 
 If you're coming from other languages, you're probably used to things breaking
 when you "upgrade" your language implementation and/or libraries.  If you want
-to run Ruby code written ten years ago on the latest version of Ruby, it's
-probably going to take some time to update it.  My current day job is in Scala,
+to run Ruby code you wrote ten years ago on the latest version of Ruby, it's
+probably going to take some effort to update it.  My current day job is in Scala,
 and if a library's last activity is more than 2 or 3 years old on Github I just
 assume it won't work without a significant amount of screwing around on my part.
 The Hamster Wheel of Backwards Incompatibility we deal with every day is a fact
-of life in most modern languages (though some are certainly better than others).
+of life in most modern languages, though some are certainly better than others.
 
 If you learn Common Lisp, this is usually not the case.  In the next section of
 this post I'll be recommending a book written in 1990.  You can run its code,
 unchanged, in a Common Lisp implementation released last month.  After years of
 jogging on the Hamster Wheel of Backwards Incompatibility I cannot tell you how
-much of a relief it is to be able to write code and reasonably expect it to
+much of a *relief* it is to be able to write code and reasonably expect it to
 still work in twenty years.
 
 Of course, this is only the case for the language itself — if you depend on any
@@ -114,24 +115,23 @@
 
 I'll be honest though: there are exceptions.  As you learn the language and
 start using libraries you'll start noticing some library authors who don't
-bother to document and/or preserve stable APIs for their libraries, and if
+bother to document and preserve stable APIs for their libraries, and if
 staying off the Hamster Wheel is important to you you'll learn to avoid relying
 on code written by those people as much as possible.
 
 #### Practicality Begets Purity
 
-This may sound a little bleak, but it's made a bit better by some other
-characteristics of Common Lisp: it's a large, practical language.  The second
-edition of Common Lisp: the Language (usually abbreviated as "CLtL2" by Common
-Lisp programmers) is 971 pages long, not including the preface, references, or
-index.  You can get a surprising amount done by writing pure Common Lisp
-without much extra support.
+Another thing to understand about Common Lisp is that it's a large, practical
+language.  The second edition of Common Lisp: the Language (usually abbreviated
+as "CLtL2" by Common Lisp programmers) is 971 pages long, not including the
+preface, references, or index.  You can get a surprising amount done by writing
+pure Common Lisp without much extra support.
 
-When programming applications in Common Lisp people will tend to depend on
+When programming applications in Common Lisp people will often depend on
 a small(ish) number of stable libraries, and library writers often try to
 minimize dependencies by utilizing as much of the core language as possible.
 I personally try to stick to fewer than ten or so dependencies for my
-applications and no more than two or three for my libraries (and preferably
+applications and no more than two or three for my libraries (preferably
 zero, if possible), but I'm probably a bit more conservative here than most
 folks.  I *really* don't like the Hamster Wheel.
 
@@ -140,8 +140,8 @@
 For example: Bordeaux Threads (the de-facto threading library for Common Lisp)
 was first proposed in 2004 and released soon after (2006 at the latest but
 possibly earlier, it's hard to tell because so many links are dead now), which
-makes it fourteen years old.  So yes, threading is handled by a library, but I'm
-not worried about it breaking my code in the next decade or two.
+makes it about fourteen years old.  So yes, threading is handled by a library,
+but I'm not worried about it breaking my code in the next decade or two.
 
 My advice is this: as you learn Common Lisp and look for libraries, try to
 suppress the voice in the back of your head that says "This project was last
@@ -152,13 +152,12 @@
 #### Extensibility
 
 Part of Common Lisp's practicality comes from its extensibility.  No one has
-been clamoring for a new version of the specification that adds features because
-Common Lisp gives users enough power to add new features to the language as
-plain old libraries, without having to alter the core language.
-
+been clamoring for a new version of the specification that adds features
+because Common Lisp's extensibility allows users to add new features to the
+language as plain old libraries, without having to alter the core language.
 Macros are what might come to mind when you hear "Lisp extensibility", and of
-course that's part of it.  Macros allow users to write libraries that would need
-to be core language features in other languages.
+course that's part of it.  Macros allow users to write libraries that would
+need to be core language features in other languages.
 
 Common Lisp doesn't include string interpolation.  You want it?  No problem, you
 don't have to wait for [Scala
@@ -217,12 +216,12 @@
 those macros to write functions, and use those functions to write more macros.
 Instead of two stratified layers it's a *feedback loop* of abstractive power.
 
-But macros aren't the only thing about Common Lisp that make it so practical and
-extensible.  Something that people often don't realize is that while Common Lisp
+But macros aren't the only thing about Common Lisp that make it so practical
+and extensible.  Something people often don't realize is that while Common Lisp
 is an extremely high-level language thanks to macros, it also has plenty of
 low-level facilities as part of the language.  It's never going to be as
-low-level as something like C or Rust, but you might be surprised at some of the
-things that the ANSI spec includes.
+low-level as something like C or Rust, but you might be surprised at some of
+the things that the ANSI spec includes.
 
 Want to see the assembly a particular function compiles down to?
 [`DISASSEMBLE`][dis] it!
@@ -316,9 +315,9 @@
 ### Get a Lisp
 
 To get started with Common Lisp you'll need to install a Common Lisp
-implementation.  Remember: Common Lisp is an ANSI specification, so there are
-multiple implementations of it, which gives you choices.  There are a bunch of
-options, but I'll make it simple for you:
+implementation.  Common Lisp is an ANSI specification, so there are multiple
+implementations of it, which gives you choices.  There are a bunch of options,
+but I'll make it simple for you:
 
 * If you're comfortable with the command line, installing packages with
   a package manager, and already have a text editor you like, choose [SBCL][].
@@ -349,7 +348,7 @@
 MacOS.  That one will work just fine to start.
 
 Emacs, Vim, Sublime Text, Atom, whatever, for now it doesn't matter.  As long as
-it can balance parenthesis, highlight comments and strings, and autoindent Lisp
+it can balance parentheses, highlight comments and strings, and autoindent Lisp
 code that's all you need to start.  Worry about shaving the editor yak once
 you're more comfortable in the language.
 
@@ -408,9 +407,8 @@
 
 The best book I've found for getting started in Common Lisp is [Common Lisp:
 A Gentle Introduction to Symbolic Computation][book-gentle].  This book really
-does strive to be gentle.  Even if you've programmed before I'd recommend
-starting here because it eases you into the language.  If you find it's moving
-too slow just skim forward a bit.
+does strive to be gentle.  Even if you've programmed before I'd still recommend
+starting here because it eases you into the language.
 
 The 1990 edition is available free from the site, and there's a 2013 reprint
 which fixes some minor errors in the 1990 version.  If you can afford it I'd
@@ -423,7 +421,15 @@
 
 * How am I ever going to remember all these weird function names?
 * Why do people use strings so rarely?
-* When do I need/not need the god damn quotation mark?
+* When do I need the god damn quotation mark?
+
+If you find the book is moving too slow, just skim forward a bit.  Skimming is
+a very useful skill to practice as a programmer.  I personally think it's
+better for authors to err on the side of explaining too much when writing books
+and documentation — expert readers should be comfortable skimming if you
+explain too *much*, but new users will be stuck wallowing in confusion if
+you're too terse.  Creating hours of newbie misery and confusion to save a few
+flicks of an expert's scroll wheel is a poor tradeoff to make.
 
 You should also join the `#clschool` channel on Freenode so you can ask
 questions if you get stuck.  For the most part people there are friendly and
@@ -460,11 +466,12 @@
 something's not clear.
 
 You should also begin to get comfortable looking up things in [the Common Lisp
-language specification][clhs] itself.  It's the ultimate manual for Common Lisp.
-It can be pretty dense at points, but can answer many questions you might have.
-You can either use the index page to find what you're looking for or just search
-on Google for "clhs whatever".  CLHS stands for "Common Lisp HyperSpec", which
-is the hyperlinked, HTML version of the spec.
+language specification][clhs] itself.  It's the ultimate manual for Common
+Lisp.  It can be pretty dense at points, but can answer many questions you
+might have if you read it slowly and carefully.  You can either use the index
+page to find what you're looking for or just search on Google for "clhs
+whatever".  CLHS stands for "Common Lisp HyperSpec", which is the hyperlinked,
+HTML version of the spec.
 
 (Some people will tell you to learn the language by just reading the spec.  That's
 ridiculous — it's like trying to learn French by reading a dictionary.  It's
@@ -493,8 +500,9 @@
 ### Lisp as a System
 
 At this point it's time to take your Common Lisp skills up a notch.  Up until
-now I've told you to just use any text editor because it's more important to get
-you some experience with the language, but now it's time to move on.
+now I've told you to just use any text editor because it's more important to
+get you some experience with the language, but now it's time to dive into the
+deep end.
 
 In most languages the development process looks something like this:
 
@@ -517,7 +525,7 @@
 
 When you embrace the Lisp way of working you'll rarely recompile and reload an
 entire project.  Usually you'll write a function (or a macro, or parameter, or
-whatever), compile just that function, maybe poke at it in the REPL a bit, and
+whatever), compile *just that function*, maybe poke at it in the REPL a bit, and
 then move on to the next function.  This has some advantages over the
 traditional compile-everything-then-run approach.
 
@@ -541,7 +549,7 @@
 In contrast, when working in languages like Scala or Python I almost never find
 myself writing one single function and compiling or running the project
 immediately.  Spinning up the compiler or running the unit tests takes at
-*least* a second or two (or, sometimes *minutes* in Scala, unfortunately) so to
+*least* a second or two (or sometimes *minutes* in Scala, unfortunately) so to
 avoid having a constant stream of gaps in my thought I end up writing a bunch of
 functions at once, and then I run the project or tests once I know they have
 a chance of working.
@@ -590,7 +598,7 @@
 Case 2 is bad, in a different way.  If you just ignore errors all the time, the
 game might now be in a weird state.  You also might lose some critical context
 that's necessary to debug the problem, unless you're also saving a core dump
-(but I don't know of many people who do that).
+(but I don't know of many people who save a core dump on every exception).
 
 In Common Lisp you can certainly choose to panic on or ignore errors, but
 there's a better way to work.  When an error is signaled in Common Lisp, it
@@ -629,6 +637,13 @@
 does happen, it just means you're back in the same situation you're in *by
 default* with other languages!
 
+Support for this style of interactive development doesn't just come from some
+fancy editor plugins — it's baked into the bones of the language.  For example:
+the standard specifies a method named
+[`update-instance-for-redefined-class`](http://clhs.lisp.se/Body/f_upda_1.htm)
+that lets you customize what happens to objects when their class is redefined!  This isn't something you'll use all the time, but something like Sketch (a Common Lisp equivalent of Java's Processing library) [uses it][sketch-uifrc] to make working with 
+
+[sketch-uifrc]: https://github.com/vydd/sketch/blob/19fe20502d26fc75752e710dfe5106ed13345c5a/src/sketch.lisp#L118-L121
 [eager]: https://www.reddit.com/r/lisp/comments/4oo1cp/common_lisp_for_clojure_programmer/d4eec68/
 [1ftaf]: https://groups.google.com/forum/message/raw?msg=comp.lang.lisp/9SKZ5YJUmBg/Fj05OZQomzIJ
 
@@ -716,6 +731,22 @@
 
 [gofai]: https://en.wikipedia.org/wiki/Symbolic_artificial_intelligence
 
+### Switch Implementations
+
+Now that you're comfortable in Common Lisp and your programming environment,
+it's time to push yourself out of your comfort zone again.  At the beginning I
+had you choose either SBCL or CCL.  Now I want you to install whichever one you
+didn't originally choose and make sure all the code you've written so far runs
+in it.
+
+This may seem a bit like running in place, but making sure your code runs in
+more than one implementation will keep you honest and force you to write
+portable code that doesn't rely on anything implementation-specific that might
+change in the next decade or two.  And you might even discover that you like
+this other implementation better than the original — maybe CCL's super-fast
+compile times make you smile, or SBCL's strong type inference catches more of
+your bugs.
+
 ### Recipes for Success
 
 The final technical book I'll recommend to every aspiring Lisp programmer is
@@ -886,6 +917,10 @@
 
 [1am]: https://github.com/lmj/1am
 
+### More Implementations
+
+todo
+
 ## Modern Common Lisp
 
 Common Lisp is old and stable, but that doesn't mean it's stagnant.  The