Ryan's Manuals

Lisp

~7m skim, 1,456 words, updated Aug 20, 2026
==> LLMs: Read this page as markdown

Top 

Magic that your boss will never let you use with a client, but you will anyways - there's nothing better!


Contents




Programming is tough. Especially at first.

Whatever you are learning or writing, keep in mind that every language was created with a set of principles and use cases in mind - some more than others.

Learn to reject your ego. Learn to love burning code.

Name things what they are. Begin with your program’s final state in mind!



Hello Lisp

elisp
(print "Hello World!")
result
;; =>  Hello World!

Some of you may say “Bwah, LISP? From the 60s?” Yes! Lisp is more common than you might think; surprisingly often the “secret sauce” of successful companies like Grammarly and Amazon is a finely crafted lispy back-end. Lisps are beautifully simple, functional tools; while many speak poorly of its age, there have been a many “eureka moments” in my first experiences with lisp where I’ve been caught off guard by the supreme effortlessness of construction and computation that lisp enables.

“Lisp has been hailed as the world’s most powerful programming language, but its cryptic syntax and academic reputation can be enough to scare off even experienced programmers.”1

Figure 1: Symbolics KB with cool Lisp editing keys

Figure 1: Symbolics KB with cool Lisp editing keys

Functions & Data

Perhaps the greatest thing lisp teaches is the philosophy - that every problem in computing can be delineated into pure functions and data, making the problems easy to understand and the code drop-dead reliable and easy to test.

The immeasurable value of this idea is difficult to understate. A variety of other programming metaphysics are taught by learning the lisp family of languages, and it is a worthwhile undertaking for any programmer worth their salt.

Many lisp dialects take this one step further by being written in its own data structures, making it completely homoiconic. This, of course, is why it is so easy to write lisp that writes itself.

“Homoiconicity is when the entirety of a language’s syntax matches the literal syntax of some of its data structures.”2

Figure 2: “The Metacircular Evaluator” from SICP

Figure 2: “The Metacircular Evaluator” from SICP

My Lisp Learning Journey

There are many implementations of lisp and many lisp-like languages, each with distinct advantages and disadvantages. For my learning, I’m going to be initially focusing on MIT lisps (adhering to the IEEE 1990 Scheme standard,) and SBCL, as these are what are used in my learning materials. Whether I settle with MIT-Scheme, Racket, Chicken or Guile depends on my mileage with each as I complete practice problems.

My favorite and most commonly used lisp-type language is Clojure, which runs on the JVM and makes the world of Java libraries easy to use via clever Java interop3.

This manual contains snippets of all kinds of lisps. If I gravitate towards one in particular, say, Racket or Clojure, I’ll breakout the lang-specific jargon into a separate manual. Currently, I am doing most of my learning in Scheme.4

MIT’s Structure and Interpretation of Computer Programs is a classic in the truest sense; the material in the tome has been used in MIT’s programs since 1980, and many of the core concepts have diffused out into reality, becoming the core of our global infrastructure. The book is available for free online in many forms.

Notes on “Learn Common Lisp”

Notes on the lisp-lang.org Common Lisp tutorial,

lisp
(format t "Hello, world!")
result
;; =>  Hello, world!

You can define functions using defun:

elisp
(defun fib (n)
  "Return the nth Fibonacci number"
  (if (< n 2)
      n
      (+ (fib (- n 1))
	 (fib (- n 2))))))

(fib 30)
result
;; =>  fib
elisp
(fib 30)
result
;; =>  832040
elisp
(setq stuff '(bear bucket ball chain rope))
(caddr stuff)
result
;; =>  ball

Common LISP Basics

Define a global variable with defparameter: (defparameter *xyz* 18)

Define a global function with defun: (defun func_name (args))

Define and use local varibles with let.

Define and use local functions with flet.

Like flet, labels defines local functions, but also allows recursive calls.

A simple number-guessing game, using arithmetic shifts (binary search,) can be written like so with a few global functions:

lisp
(defparameter *big* 100)
(defparameter *small* 1)

(defun guess-my-number ()
  (ash (+ *small* *big*) -1))

(defun smaller ()
  (setf *big* (1- (guess-my-number)))
  (guess-my-number))

(defun bigger ()
  (setf *small* (1+ (guess-my-number)))
  (guess-my-number))

(defun start-over ()
  (defparameter *small* 1)
  (defparameter *big* 100)
  (guess-my-number))

(start-over)
result
;; =>  50

In higher-order functions, #'x stands in for (function x).

Here is another example program showing parameters being defined, functions being defined, string insertions, comments, and more:

lisp
;;;; Prog5: "Wizard Adventure Game" RCF 2018 - Land of Lisp p.70

(defparameter *nodes*
  '(
    (living-room
    (you are in the living-room. a wizard is snoring loudly on the couch.))
    (garden
    (you are in a beautiful garden. a well is in front of you.))
    (attic
    (you are in the attic. there is a giant welding torch in the corner.))))

(defparameter *edges*
 '(
    (living-room (garden west door) (attic upstairs ladder))
    (garden (living-room east door))
    (attic (lving-room downstairs ladder))))

(defparameter *objects*'(whiskey bucket frog chain))

(defparameter *object-locations*
  '(
      (whiskey living-room)
      (bucket living-room)
      (chain garden)
      (frog garden)))


(defun describe-location (location nodes)
  (cadr (assoc location nodes)))

(defun describe-path (edge)
  `(there is a ,(caddr edge) going ,(cadr edge) from here.))


(defun describe-paths (location edges)
  (apply #'append
    (mapcar #'describe-path
      (cdr (assoc location edges)))))

(defun objects-at (loc objs obj-locs)
  (labels
    ((at-loc-p (obj)
      (eq (cadr (assoc obj obj-locs)) loc)))
      (remove-if-not #'at-loc-p objs)))

;; Let's run and see:
(describe-paths 'garden *edges*)
THEREISADOORGOINGEASTFROMHERE.

Appendices

Emacs outshines all other editing software in approximately the same way that the noonday sun does the stars. It is not just bigger and brighter; it simply makes everything else vanish.

-– Neal Stephenson, In the Beginning was the Command Line (1998)

SLY Commands

KeybindingFunction (if applicable)Effect
C-M-xsly-eval-defunEvaluate the block of lisp code
C-x C-esly-eval-last-expressionEvaluate sexp at point (just behind cursor)
C-c C-csly-compile-defunCompile defn (the outmost expression)
C-c C-ksly-compile-and-load-fileCompile whole buffer (of saved file)
C-c C-s C-ssly-stickers-dwimSet or remove a sticker at point
C-c C-s C-rsly-stickers-replayReplay sticker values
C-c Isly-inspectEval an expression and inspect the result
M-p / M-nNavigate up/down in REPL

C-h k can be used to find out exactly what a keybinding does.

SLIME Simple Commands

KeybindingEffect
M-x slimeOpen the SLIME repl
C-c C-cRecompile a definition
C-M-xEvaluate expression and put result in minibuffer
C-c C-pEvaluate and pretty print the result
C-c C-rEvaluate the selected region
C-c C-lLoad a file into SLIME
C-c C-kRecompile and run file (Save first C-x C-s)
C-c C-zGo to SLIME REPL
C-M-qReindent s-expression
C-c M-qReindent whole function
C-c C-uUndefine function
M-p M-nNavigate up/down in REPL

Geiser MIT REPL Keybindings

This is for editing MIT Scheme files while reading SICP.

KeybindingCommand or Function or DefinitionNote
M-x geisergeiserOpen the Geiser REPL
C-c C-zgeiser-mode-switch-to-replGo to Geiser REPL
C-c C-ageiser-mode-switch-to-repl-and-enterGo to REPL and enter module
C-x C-egieser-eval-last-sexp
C-c C-c / C-M-xgeiser-eval-definition
C-c C-rgeiser-eval-region
C-c C-bgeiser-eval-buffer
C-c C-kgeiser-compile-current-buffer
C-c M-ogeiser-repl-clear-bufferIn REPL - clear
M-p/n(Common) Previous and Next item in REPL
C-c \geiser-insert-lambdaInsert a lambda character

Use C-h k to check what keybindings are bound to.

Why use Functional Languages?

To expand my programming horizons, I chose to read a book on CLisp, which was fantastic. After this I began applying functional techniques everywhere else; these languages change the way you approach problems. I’m now reading through SICP and Land of Lisp, and enjoying both immensely.

Whichever LISP you use, I recommend using the rlwrap program to enhance your working experience. Running, for instance, rlwrap guile adds history, readline and bracket matching to the REPL, which can be a huge quality-of-life improvement.

Begin with the End in Mind (2022)

I am learning lisp because I want to learn a language that will allow me to accomplish my major life goals and minimize pain and stress while doing so.

The language I choose for this task must then neccessarily be:

  1. A well-established language (cannot be the new hotness)
  2. Powerful and flexible to a variety of use cases
  3. Broad platform and runtime support with minimal tooling
  4. Large community and many good libraries
  5. Many ways to edit, not reliant on one IDE or system
  6. Ideally can compile to C and has C interop
  7. Absolutely not locked to a single platform or provider
  8. Able to be performantly hosted on my home-lab hardware

Common Lisp seems to satisfy these requirements.

Other Resources


  1. From “Land of Lisp” ↩︎

  2. Definition from https://mitranim.com/posts/lang-homoiconic  ↩︎

  3. See Clojure Java Interop Guide and Java Interop in the official docs. ↩︎

  4. This didn’t last long, though I still plan to go through SICP. ↩︎



Site Directory

Pages are organized by last modified.



Page Information

Title: Lisp
Word Count: 1456 words
Reading Time: 7 minutes
Permalink:
https://manuals.ryanfleck.ca/lisp/





Work licensed under the CC BY-SA 4.0 license unless otherwise specified.