83 comments

[ 4.5 ms ] story [ 200 ms ] thread
This book is beautiful and provides a pretty decent introduction to Common Lisp with a variety of simple games that it builds throughout to demonstrate various techniques.
This book is well worn, dog eared, and on my home office book shelf. While many people criticize it, for legitimate reasons, it is still a fun and wonderful journey through Common Lisp. I wish more books were written in this irreverent and whimsical style.

If however you want a more traditional and "from zero" introduction to Lisp, then "Common LISP - A Gentle Introduction to Symbolic Computation"[0] may be better. If you already know a little bit of Lisp and want to step up your abilities then "Practical Common Lisp"[1] is probably what you are after.

[0] https://www.cs.cmu.edu/~dst/LispBook/

[1] http://www.gigamonkeys.com/book/

I second the recommendation for Practical Common Lisp, even for complete beginners and newcomers to Lisp. It covers the very basics, and the writing style is accessible and patient.
Lisp has such an amazing literature. Aside from those 2, which are truly nice, there's The Little Schemer, SICP, On Lisp, Lisp in Small Pieces, PAIP and many others (like CLtL, The Art of the MOP, etc).

I personally think Lisp in Small Pieces is really underappreciated.

Is there such a thing as a bad Lisp book? ;) Maybe there are only ones you're not ready for yet... (I've been unsuccessfully searching for a hardcover of Art of the Metaobject Protocol for a while, I can make myself ready for it once I have it.)

In HN tradition where we all recommend every book we've ever read similar to the submitted one (and Land of Lisp is worth reading), an overlooked recently published booklet I found is Common Lisp in the Wild: https://www.darkchestnut.com/book-common-lisp-application-de... Common Lisp is so flexible in letting you develop the way you want to develop, but if you're a professional programmer looking for a Maven-esque template of "structure your project in this familiar way without sacrificing any of the interactive Lisp dev experience, enumerate version-pinned dependencies, one-step make to build, test, run, deploy the final artifact" like I was that book's suggestions are worth the entry fee and you're left with a stable foundation to deviate from.

> is there such a thing as a bad Lisp book?

Yes, there exists a certain a really awful book from the 1980's about making your own Lisp in C, which has recently been reprinted in essentially its original form.

I nearly started working through that, would you mind sharing why you think it is a bad book? thx
I’m pretty sure it’s because the lisp that book makes isn’t an exact lisp; There are many features lacking and some fundamental concepts are wrongly implemented; However for developing C skills, it’s pretty good. Wouldn’t recommend learning Lisp with that though.
oh you're correct it is meant to develop C skills not learn Lisp
The 900-something lines of C code documented by the book Interpreting Lisp, which can now be found on Github, is not something I would recommend for teaching C beginners.

From a best practices point of view, it is pretty awful.

https://github.com/Apress/interpreting-lisp

> Is there such a thing as a bad Lisp book? ;) Maybe there are only ones you're not ready for yet... (I've been unsuccessfully searching for a hardcover of Art of the Metaobject Protocol for a while, I can make myself ready for it once I have it.)

The Art of the Metaobject Protocol is truely a delightful book. While it is probably not very useful for practical programming - it isn't meant as a teaching book for beginners, it certainly is enlighting how to bootstrap an object oriented system on a common lisp without any object facilities. So if you can get hold of one, grab it!

Personally, I am not a fan of the Keene book. I know, many people here disagree with my view, but I neither like its writing style nor the programming style it presents. I would strongly recommend Practical Common Lisp instead.

> the programming style

There is a lot of programming style to be learned from the Art of the Metaobject Protocol.

Yes, from Amop :) But not from the Keene book.
I'd think from both.
> Is there such a thing as a bad Lisp book?

there are not many really bad ones, but there are some and I'm not going to mention them. ;-)

I do recommend Practical Common Lisp not only for Lisp newcomers. The concepts teached apply to programming in a bigger context. Lisp is here only a vehicle (a very good one).
I'm going through this book now. It has a different style from LoL but I do find it suits me better. It feels at least more structured :)
If you like this sort of thing, here are some others in a similar humorous style for other languages.

1. Kaufman, Roger. A FORTRAN Coloring Book (probably the first funny programming book -- from 1978).

2. Lipovača, Miran. Learn You A Haskell for Great Good.

3. Hebert, Fred. Learn You Some Erlang for Great Good (inspired by the Haskell book).

4. Felleisen, Matthias. Realm of Racket (basically Land of Lisp for Racket. Oddly, nobody's done a "Commonwealth of Clojure" or "Society of Scheme" yet.)

1+ for “commonwealth of Clojure”—but shouldn’t there be a j somewhere in that? Cjommonwealth? (Pronounce j like y and it kinda works.)
> nobody's done a "Commonwealth of Clojure"

Higginbotham, Daniel. Clojure for the Brave and True.

https://www.braveclojure.com/

I really loved the part where Lady Gaga explained multitasking.
I loved Land of Lisp, but found Clojure for the Brave and True annoying. To me, LoL is hilarious, while CftBaT tries to be funny, but fails.
Hmmm I think I remember a few failed jokes but I found the actual coverage of the language pretty good, wdyt? I guess for a book like this you are not really looking for a comedy best seller, no? :-)
I guess the thing is that when an attempt at humor fails, which is obviously subjective, it starts to distract from the content.
I agree it is subjective. I actually open Clojure for The Brave and True book from now and then just because I find so much of it truly hilarious. The hilarity is what really helped me get Clojure. I also like the Land of Lisp and find it funny as well.
I suspect this is one of the best books on Clojure out there ("suspect": I'm working through a couple of different ones on and off).
Clojure Applied (Alex Miller) or Programming Clojure 3rd Ed (Alex Miller / Stuart Halloway) would be my picks but I don't know how beginner friendly they are.

They're certainly not as colourful as brave but found the pace and coverage good

Why’s Poignant Guide To Ruby is also in this vein, though a bit weirder.
_why's book is what got me into programming. I still love Ruby, even though I've only had single digit months where I was able to program professionally in it
Realm of Racket is such a strange book. It feels like they tried really hard to follow LOL or "why's (poignant) Guide to Ruby" aesthetics/structure, with mixed results.

Also, I know this is silly but I remember the book followed this guy who was supposed to be "the hero" that was always sad or concerned, or frowning, in every picture, right on to the end of the book (or so I remember it...). I know it is silly but that put me down :-p

LYAH is a great introduction for Haskell in my opinion. It helps make an intimidating language more approachable. And once you see that it's not all that intimidating, it's easy to find resources for yourself and keep learning Haskell.

The Haskell IRC community is a great resource as well, and probably one of the friendliest around. (#haskell on freenode)

Only from skimming the first few pages of "Why's (poignant) guide to Ruby" I wanted to learn Ruby.

I didn't checked recently, but I found bizarre (maybe not the right word) how the author one day decided to disappear and nuke his Internet presence.

https://poignant.guide/

I love this guide! A friend showed it to me and I still quote lines from it often. I like the bit about "our own recliners", I tell my friend that someday him and I will have our own recliners. Another line I vaguely remember is when he's made a backpack for a bug out of a leaf. I think he puts a skittle and a battery in there and then says "that should last him". The writing style is great.
Yes, that was interesting. I read about it at the time (I was doing Ruby around then). Another one on the same lines was Mark Pilgrim (author of Dive into Python and similarly-named books for Python 3 and HTML 5, IIRC).
What are the criticisms of it? Curious.
Wonderful book, read it years ago, and read Grahams Common List the Language, and before that the little lisper, and before that ansi Common Lisp. I don't remember very few of any of those books but hopefully something beneficial remains.
(comment deleted)
I bought this book years ago even though I had already been programming in Common Lisp for 20 years at that time. I really like Conrad Barski's writing and that was sufficient reason to buy the book.
"Loving Common Lisp, or the Savvy Programmer's Secret Weapon" is also a very good book on Lisp.

  CL-USER> (if (not-known-by-p 'you)
             (author-p 'your-parent-commenter 'Loving-Lisp)
           ) 
  T
;) sorry, just approximate syntax
As someone that started learning lisp with this book I recommend not starting with this book, and instead reading Practical Common Lisp.

Some of the tutorials in the book use some fairy awkward conventions (e.g. using lists of symbols to create strings).

I enjoyed the book, but had to unlearn some things afterwards.

I thought it is to help to learn list manipulation. String is great but is a super coat. But I do agree this should not be the only book. In fact Piap is better.

The whole Common Lisp learning is hindered by suddenly you have a function that do magic. And nil does not help.

Really wish there is a lisp book learning using the kernel (lisp 1.5 which can be easily implemented using itself).

(comment deleted)
Author of LOL here, if there are any questions!
(comment deleted)
What do you think about making a second edition?
I would say "Realm of Racket" is really the second edition to "Land of Lisp"- The fact is that most lisp developers now use either Racket Scheme or Clojure, so those are really the only markets that could support a rework of LOL in 2019. I've tried a couple of times in the past to work with someone on a Clojure port, but just haven't been able to make the coauthor+publisher work out right to get it launched.
If you ever manage to get that off the ground and onto shelves, that would make me a very happy kiddo.

Thanks for writing one of the most enjoyable programming books out there.

Flick me a message if you're interested in chatting to Manning at any stage
I'll have to check it out. I'm surprised about your impression of where most lisp developers are in 2019 vs 2010 -- from my (admittedly still rather outsider) perspective the CL ecosystem looks significantly healthier in 2019 than in 2010. Clojure[Script] remains dominant but has lost a lot of steam, Racket took some high-profile Lispers but still doesn't have the production success stories that both CL and Clojure have and language progress is likely to be stalled a while as the transition to a Chez core continues, and CL usage and useful libraries have despite it all grown. The main IRC channel is active, there's a C++ integration story (Clasp), more frequent CL-related HN submissions, the European Lisp Symposium this year had a lot of new first-time attendees, and new books with an emphasis on helping production programmers (e.g. Common Lisp Recipes) were published.
Hey Dr Barski. I'm actually reading your book right now. I do have a question. How do you write Lisp effectively? And by that I mean, Lisp seems to be written from the inside out due to the nested lists. Is there something that makes it more natural to write: (trim-string (get-string '(some data))) Or do you need to know that you're going to call trim before you get the string? Hope that makes sense.
how do you write it in other languages?

   sin(cos(10.4));
or

   v = 10.4;
   c = cos(v);
   s = sin(c);
in Lisp one might write:

   (let* ((v 10.4)
          (c (cos v)))
     (sin c))
really old style:

   (prog (v c s)
     (setq v 10.4)
     (setq c (cos v))
     (setq s (sin c))
     s)
Why not write it as in lisp as:

    (sin (cos 10.4))
The question was for alternatives to code that reads inside->out. I personally don't have a problem with it, but I can see that many languages have a more procedural/imperative top->down control flow by default. A Java programmer might prefer that, where a Lisp programmer will be trained to alternate while reading between inside->out and outside-in in code.
Still using those long expression is unfair

A(b(c)) are 2 function calls.

Hence

(A (b c))

is the fair abd equal expression. And you inside out whilst valid and in fact easier to read (as more normal) would need precedence rule in other scenario.

But those examples just not right.

Thanks for the reply! I'd go the first route unless method chaining was available.

  SomeData.ToString().Trim()
I would like to write idiomatic Lisp code and it's getting easier to read the nested expressions but it breaks the flow to leave the expression and wrap it. Another user mentioned using a command with Emacs to escape the expression and auto wrap it. That might be what I'm looking for.
That's the same as:

    (chain somedata (tostring) (trim))
It's a macro away in Lisp. But I would not use it much, since it kind of defeats the advantage of using nested expressions -> they are actually nested.

  This is the TXR Lisp interactive listener of TXR 215.
  Quit with :quit or Ctrl-D on empty line. Ctrl-X ? for 
  cheatsheet.
  1> [chain tostring trim-str]
  #<intrinsic fun: 0 param + variadic>
  2> [*1 3.4]
  "3.4"
  3> [[chain tostring trim-str] 3.4]
  "3.4"
No ready example of a datatype that requires trimming after a string conversion! We'd have to write one:

  4> (defstruct foo nil
       (:method print (me stream pretty-p)
         (put-string "foo " stream)))
  #<struct-type foo>
  5> (tostring (new foo))
  "foo "
Okay we are in business:

  6> [[chain tostring trim-str] (new foo)]
  "foo"
Method chaining syntax is possible, but with actual methods only. Most library functions aren't methods; you have to roll your own:

  1> (defstruct accum nil
       (val 0)
       (:method inc (me : (delta 1))
         (inc me.val delta)
         me)
       (:method mul (me : (factor 2))
         (upd me.val (* factor))
         me))
  #<struct-type accum>
  2> (new accum).(inc).(inc).(mul 3)
  #S(accum val 6)
  3> (new accum).(inc).(inc).(mul 3).val
  6
Support for idiom isn't the result of a conscious design decision; it just arises naturally when you have this sort of postfix syntax.

TXR's dot syntax is a very straightforward sugar for Lisp structure. Basically x.y.z == (qref x y z). Whitespace is not allowed around the dot. Numbers are also not allowed: 3.4 is a floating-point constant and a.3 or 3.a are invalid. If the leading element is missing, then it's the uref (unbound ref) operator: .y.z == (uref y z). This compiles to a function resembling (lambda (obj) obj.y.z).

The way I do it, is that in my editor, I can type:

'(some data|)

Where | is my cursor.

And then I have a keybinding that moves my cursor to the front and wraps around like so:

(| '(some data))

So I can type the next thing:

(get-string| '(some data))

Press it again:

(| (get-string '(some-data)))

And so on.

That way, even though the code is visually nested, I can write it in logical order from what eval first to what eval last. A good editor for editing lisp code makes that possible, as I showed, and many other operations.

Basically, get yourself accustomed to a good Lisp editor such as Emacs and I'm sure you'll find that problem will disappear. For me, it's even more productive now typing wise, because I can make more structural edits to my code, which is way faster.

I don't think he's talking about how to type the characters... He's probably asking: you're inverting, visually, the order of operations. When does start becoming natural?
This is just what I've been looking for!

I've been searching for this and see there are commands for navigating s expressions but I haven't found this example. Is this a built-in command? Is there name for this action?

There are some built-in commands in Emacs for navigating, cutting and transposing s-exps, but what you want is probably a step further - a package like Paredit[0], that gives you much more sexp-specific actions, and automatically keeps parens balanced for you. See animated examples at [1] and a cheat sheet at [2].

There isn't, as far as I know, a default keybinding for what GP did - navigate up the SEXP, wrap in parens and place point before the inner SEXP. You can get very close to it with two steps: paredit-backward-up [C-M-u] and paredit-wrap-round [M-(], though it gets confused by the hanging quote a bit. To demonstrate on GP's example:

  '(some data|)
  '|(some data)    ; after C-M-u
  '(|(some data))  ; after M-(
So the quote is in a wrong place. You could probably whip a command doing OP's thing that calls paredit-backward-up and paredit-wrap-round, with a conditional that backs up a few chars if it detects a piece of syntactic sugar attached to the SEXP (quote, quasiquote, comma, reader macro invocation). Somebody has likely already done it, or maybe there is a less known Paredit command for that - I don't know. If anyone does, please chime in.

Myself, I mostly use wrapping, barfing and slurping.

--

[0] - Available in Emacs' package manager on MELPA, or here: https://github.com/emacsmirror/paredit.

[1] - http://danmidwood.com/content/2014/11/21/animated-paredit.ht...

[2] - https://github.com/joelittlejohn/paredit-cheatsheet

For anyone stubborn enough to want to do this with Vim, I've come up with this.

  function NestExpression()
      " Get end paren pos
      " Returns [0, 0] if not in parens.
      let save_cursor = getpos('.')

      " If line not set to zero, append
      let end_paren_pos = searchpairpos('(', '', ')')
      if end_paren_pos[0] > 0
          execute "normal! a)"
      else
          " We're not in a set of parentheses
          return
      endif

      " Return to the inside of the parentheses
      call setpos('.', save_cursor)

      " If line not set to zero, start insert
      " mode, prepend and move cursor left
      let end_paren_pos = searchpairpos('(', '', ')', 'b')
      if end_paren_pos[0] > 0
          call feedkeys("i( \<LEFT>")
      endif
  endfunction

  nmap fj :call NestExpression()<cr>
Let Over Lambda is LOL too :)

Enjoyed your book, currently teaching my nephew some lisp with it!

Are you plan to write any new Lisp books? Or any book for that matter?

Would be interested in reading anything you write :)

I also co-wrote "Bitcoin for the Befuddled" and participated in "Realm of Racket". I am sort of enamoured by other media now (video, animation, interactive web stuff) and if I do anything else it will be in that vein in the future (though I have struggled with akrasia on that front)
absolutely loved it, basically learned coding with it.

extended the games a lot and even ported them later on to other languages.

thanks a lot :)

Thanks for the book! It was the reason I finally started to really learn LISP apart from just dabbling with it. It did serve as a great way to get over the "scary-ness" of learning LISP. :)
Did you draw the pictures yourself? I really like the long final comic story, and several times thought about making some roguelike ascii game with this background (choosing a guild with specific skills, killings various kinds of bugs, etc.), but I am too lazy for having actually written it... Thank you for that!
Yes, drew everything myself, took years of my free time given the size of the book :)
I bought this book (physical copy) a few years ago and loved it. It may not be perfect, but for me, as an already experienced developer, it was a great intro to the world of Lisp.
My companies entire backend is Common Lisp.

We have quite a few of these books laying around, along with Practical Common Lisp.

I had dabbled in LISP before picking up this book. I'm quite happy that I did pick it up eventually to learn how to actually get something done with LISP.

After this book, I picked up "Practical Common Lisp" (going through that one at the moment).

So far, I found LoL to suit me less than a more traditional book like PCL, but it did help me actually get a sense of LISP.

Also, the song is catchy.. Simple but refined guaranteed to blow your mind... the land of lisp ;-)