4 ms·
Notes on Graham's ANSI Common Lisp (2024)
- brabel 1y agoIs this basically a 16-chapter (plus a few appendixes) code review?!?
- mananaysiempre 1y agoIt’s a review of a book consisting of 16 chapters (plus a few appendices), which does seem mostly concerned with the code examples in it. But then the book is structured around them, too.
- danilor 1y agoI appreciate this as someone learning lisp for the first time! While I'm here I'll ask: does anybody have a recommendation for resources on learning lisp that focus on how the interpreter/compiler works? Here's what I tried so far: 1) Started Practical Common Lisp, but I found it lacking in the specifics. Then I 2) tried going to the specification but that was way too much. Then I 3) tried Common Lisp The Language and, while I liked the precise definitions a lot, it was a lot to keep in mind at the same time as learning the fundamentals. Right now I'm 4) back at Practical Common Lisp, skipping most of the text and reading surrounding paragraphs whenever if I find a piece of code I don't understand. I wanted something that will not explain the standard library; I'd rather read the documentation for that. I wanted to know more precisely what happens throughout the program's life: Like, is behavior when running a script in "interpreter" mode guaranteed to be the same as when running in "native compiled code"? At what point does the compiler create an intermediate representation? Why does SBCL not use LLVM? At what point are #-starting words(read macros?) evaluated and how is that different from interpreting to compiling. How do I control the amount of optimization the compiler will do? Will the interpreter ever try to optimize? Is garbage collection implementation-defined? How will implementations change in behavior?
- anthk 1y agoECL will run everything SBCL can, but far more slowly, albeit the gap it's closing. On QuickLisp, use Ultralisp, as an updated mcclim with an up to date clx it's like night and day on speed. If you use Portacle, just run: (ql-dist:install-dist "http://dist.ultralisp.org/ http://dist.ultralisp.org/" :prompt nil) Otherwise, install Ultralisp and then eval that function to get an updated QL base). Recommended book: https://www.cs.cmu.edu/~dst/LispBook/ https://www.cs.cmu.edu/~dst/LispBook/ Portacle which bundles Emacs + SBCL: https://portacle.github.io/ https://portacle.github.io/
- bigdict 1y agoLisp In Small Pieces
- jnpnj 1y agoSeconded, it's a great book.
- MangoToupe 1y agoYep this is the best way into the heart of LISP
- drob518 1y agoThirded.
- deleted 1y ago[deleted]
- jjtheblunt 1y agoIt's instructive to read the Guy Steele papers from 48ish years ago like "Lambda: The Ultimate Goto" ( https://en.wikisource.org/wiki/Lambda:_The_Ultimate_GOTO https://en.wikisource.org/wiki/Lambda:_The_Ultimate_GOTO ) as they go into how the Lisp-y abstractions can correspond to machine code (as in interpreters and compilers).
- drob518 1y ago
- anthk 1y agoA must read. Get the figures too. https://www.cs.cmu.edu/~dst/LispBook/ https://www.cs.cmu.edu/~dst/LispBook/ A no brainer setup: https://portacle.github.io/ https://portacle.github.io/ happy hacking.
- EdwardCoffin 1y agoThis book was an important part in my learning of Lisp, along with Common Lisp the Language 2ed. It did leave me with a few biases that took a while to overcome though, like biases against CLOS and verbose names. I consider this book to be almost like a forerunner of the style of book that JavaScript: the Good Bits is, in that it is advocating one's use of a language to a particular subset rather being an impartial description of the whole language.
- aarestad 1y agoSame, and I actually learned from this book in a class from this very professor!
- f1shy 1y agoAnd probably the aversion to loop facility…
- EdwardCoffin 1y agoWell to be fair I already had that aversion, though I will use that on occasion. Ironically enough I am an aficionado of the Waters series facility [1], which requires one to write Loop definitions for certain constructs (like defining new producing forms), so my efforts to avoid using Loop led to me using it. I think Loop doesn't deserve the hate it gets. I don't particularly like it, but I don't dislike it that much. [1] https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node347.html https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node347.html
- dapperdrake 1y agoShameless plug: I got SERIES to work with parenscript. Way better than expected.
- TurboHaskal 1y agoIt's funny how I started this way as well, and a decade later my Common Lisp code couldn't be more procedural and CLOS and LOOP heavy.
- defgeneric 1y agoThese notes may appear to be overly critical or an extremely pedantic reading but they're pretty good, and it's bit like like having the teacher across from you while you're reading. But some notes are a little excessive and the teacher comes off as overbearing. For example, the emphasis on the function style is itself pedagogical, hence the avoidance of `loop` and the preference for recursion over iteration. Some are more excessive than that, like Chapter 2 page 18 (the author shouldn't use ~S if it hasn't been properly introduced yet, so sticking with ~A is actually the right choice.). Overall it's a great guide to reading, especially as it gives the student a sense for the higher-order stylistic considerations when writing a more malleable language like lisp.
- cryptonector 1y agoThese are very good notes. Here's a few of my notes on these notes: > Naming: Like Unix, Graham likes short names, often to the point of crypticness. See my notes on naming for a better way. Eh, you should see Haskell, where conventions are to use `x` for an object of some type and `xs` for a list of `x`, for example. And not just x/xs, but h/hs, etc. Once you get used to thinking of polymorphic functions as mathematical functions then this starts seeming ideal rather than cryptic. > Loops: Graham avoids loop, because it is so easily misused and different from the functional programming style. Sometimes, however, loop is the clearest simplest way to write something. I agree, but this is probably didactic. Many Lisp teachers insist on students learning to think of recursion as a natural way to do iteration. I'm not sure I agree with that viewpoint, but I don't think it's unreasonable. The issue I have is that one really has to learn how to recognize tail recursion instantly, even mutual tail recursion, and then also how to recognize when non-tail recursion (especially mutual non-tail recursion) gets optimized by the compiler into a loop with an explicit stack (if at all). > Preference for recursion over iteration, even if it might lead to code that causes stack overflows on very long lists. Yes, well, see above. I agree that starting Lisp programmers will take some time to learn how to use tail recursion, but it's not a problem for a) an experienced Lisp programmer, b) a Lisp teacher who is trying to drive this point home. > Backtraces are incredibly useful for debugging. Be aware though that tail-call elimination may have removed some function calls from the stack. This is true in many languages. I've seen this in C. You have to get used to it because tail call optimization is so important. > bfs is a terrible name, because it says how it works, not what it does. Sometimes "how it works" has to bleed into the naming somehow. Generally (i.e., not just in Lisp) this function could be `search` (which is what TFA wants) in some namespace/package/whatever that where the function implements [part of] an interface and the provider's name denotes that this is a breadth-first search, but it's very important to understand the trade-offs of depth-first and breadth-first searching and which you get needs to be observable somewhere.
- lapsed_lisper 1y agoIDK how much this matters, but the Common Lisp standard doesn't mandate tail call elimination. So although many implementations offer it (usually as a compiler thing), it's conceptually an implementation-dependent detail that borders on a language extension: if your code actually depends on TCE for correct execution, that code might exhaust the stack under ordinary interpreter/compiler settings, and differently across different implementations. So for Common Lisp, if you want to use standardized language features standardly, it's quite reasonable to reach for iteration constructs rather than tail recursion.