# Lisp

> Published  Jan 01 0001, last updated Sep 09 2025  
> By Ryan Fleck <hello@my-name-dot-ca> and written without LLMs!  
> Original manual at <https://manuals.ryanfleck.ca/lisp/>  
> Incredible writing of astonishing quality and insight - Happy Hacking!


# Hello Lisp {#hello-lisp}

```lisp
(defparameter *langs* '( clisp racket scheme ))

(princ "Hello, ")
(princ *langs*)
```

Bwah, _LISP?_ From the _50s?_ Yes- Lisp is more common than you might
think; often the "secret sauce" of successful companies like
[Grammarly](https://tech.grammarly.com/blog/running-lisp-in-production)
and
[Amazon](https://groups.google.com/forum/#!topic/comp.lang.lisp/SD-8ULlEfy0%5B1-25%5D)
is a finely crafted lispy back-end. Lisps are beautifully simple and
functional tools; the following article contains my impressions as I
begin to learn the CLISP dialect. While many speak poorly of its age,
there have been a few occasions in the first 30 pages where I've been
caught off guard by the effortlessness of construction and computation
that lisp provides. I almost cried the first time I saw LISP handle
rational numbers.

It is important to note that there are many implementations of lisp,
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.

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**.[^fn:1]

> 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. Those dark days are finally over ---
> Land of Lisp brings the power of functional programming to the people!

{{< figure src="/images/SymbolicsKB.jpg" caption="<span class=\"figure-number\">Figure 1: </span>Symbolics KB" >}}

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.


# Emacs, SLIME, and ORG {#emacs-slime-and-org}

Emacs is a text editor in the same way that a cell phone makes phone
calls. This entire file is an .org file that is converted to a webpage
by Hugo, allowing me to have ****inline executable code cells**** and other
handy features.


## Installing Emacs on Windows and OSX {#emacs-on-windows}

...I know, I know, heresey. I'm typing this in VS Code too. Still trying
to get some quicklisp packages working via SLIME.

First install Chocolatey, the package manager, then run this command:

```ps2
choco install sbcl pyenv-win nvm.install elixir git -y
choco install emacs imagemagick msys2 -y
```

Open the msys2 shell and run:

```nil
pacman -S mingw-w64-x86_64-openssl
```

Add that .dll to the PATH:

```nil
C:\tools\msys64\mingw64\bin
```

Add something like this to your Emacs config. You can always use M-x
describe-variable or describe-command.

```lisp
;; Ryan's Windows EMACS Config
;; C-M-x to interpret a function, have fun.

;; Add package repository for installing slime, etc.
(add-to-list 'package-archives
             '("melpa-stable" . "https://stable.melpa.org/packages/") t)
(package-initialize)

(require 'package)
(require 'srefactor)
(require 'srefactor-lisp)

(custom-set-variables
 ;; custom-set-variables was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(custom-enabled-themes nil) '(package-selected-packages '(srefactor
 slime)))

(custom-set-faces
 ;; custom-set-faces was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(default ((t (:family "Noto Mono" :foundry "outline" :slant normal :weight normal :height 120 :width normal)))))

;; (setq inferior-lisp-program "/opt/sbcl/bin/sbcl")
(setq inferior-lisp-program (executable-find "sbcl"))

(add-to-list 'load-path "~/AppData/Roaming/slime")
(require 'slime-autoloads)

(load (expand-file-name "~/quicklisp/slime-helper.el"))
;; Replace "sbcl" with the path to your implementation

;; Semantic Refactor keybindings
(global-set-key (kbd "M-RET o") 'srefactor-lisp-one-line)
(global-set-key (kbd "M-RET m") 'srefactor-lisp-format-sexp)
(global-set-key (kbd "M-RET d") 'srefactor-lisp-format-defun)
(global-set-key (kbd "M-RET b") 'srefactor-lisp-format-buffer)

;; (global-set-key (kbd "M-RET b") 'srefactor-lisp-format-buffer)
```

**Emacs Packages to Install:**

-   slime
-   srefactor
-   srefactor-lisp
-   magit
-   org
-   markdown-mode
-   modus-themes (modus-vivendi-tinted)

Take note of
[this page
on super and hyper keys](http://xahlee.info/emacs/emacs/emacs_hyper_super_keys.html) -- it is good to use your keyboard, whether it
is on a MacBook or a full mechanical keyboard, to its fullest.

```lisp
;; On Windows:
(setq w32-pass-rwindow-to-system nil)
(setq w32-rwindow-modifier 'super) ; Right Windows key

(setq w32-pass-apps-to-system nil)
(setq w32-apps-modifier 'hyper) ; Menu/App key

;; On OSX:
(setq mac-left-option-modifier 'super)
(setq mac-right-option-modifier 'control)
(setq mac-command-modifier 'meta)
(setq ns-function-modifier 'hyper)
```

Hide your menu, tool, and scroll bars:

```lisp
(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
```


# Notes on <span class="underline">Learn Common Lisp</span> {#notes-on}

Notes on the [lisp-lang.org](https://lisp-lang.org/learn/) Common Lisp tutorial.

```lisp
(format t "Hello, world!")
```

```text
Hello, world!
```

You can define functions using `defun`:

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

(fib 30)
```

```text
FIB
```

```lisp
(fib 30)
```

```text
832040
```

```lisp
(setq stuff '(bear bucket ball chain rope))
(caddr stuff)
```

```text
BALL
```


## Common LISP Basics {#common-lisp-basics}

<ol class="org-ol">
<li>Define a **global variable** with _defparameter_:
`(defparameter    *xyz* 18)`</li>

<li>AKA top-level definition, dynamic variable, special variable.</li>
<li>Don't forget the _earmuffs_!</li>
<li>`(defvar *xyz* 18)` will set but not overwrite.</li>

<li value="2">Define a **global function** with _defun_:
`(defun func_name    (args))`</li>

<li>Functions appear after `(args)`:</li>
<li>`(defun example_function () (commands))`</li>

<li value="3">Define and use **local varibles** with _let_.</li>

<li>`(let ((x 1)(y 2)) (commands))`</li>
<li>These variables are only active in the function body.</li>

<li value="4">Define and use **local functions** with _flet_.</li>

<li>`(flet ((func_name (args) (commands))) (commands with function))`</li>
<li>Again, the function only works in the _flet_ list.</li>
<li>Multple functions can be defined in the () after _flet_.</li>

<li value="5">Like _flet_, _labels_ defines local functions, but also allows
recursive calls.</li>
</ol>

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)
```

```text
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*)
```

|       |    |   |      |       |      |      |       |
|-------|----|---|------|-------|------|------|-------|
| THERE | IS | A | DOOR | GOING | EAST | FROM | HERE. |


# Appendices {#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 {#sly-commands}

| Keybinding  | Function (if applicable)  | Effect                                      |
|-------------|---------------------------|---------------------------------------------|
| C-M-x       | sly-eval-defun            | Evaluate the block of lisp code             |
| C-x C-e     | sly-eval-last-expression  | Evaluate sexp at point (just behind cursor) |
| C-c C-c     | sly-compile-defun         | Compile defn (the outmost expression)       |
| C-c C-k     | sly-compile-and-load-file | Compile whole buffer (of saved file)        |
| C-c C-s C-s | sly-stickers-dwim         | Set or remove a sticker at point            |
| C-c C-s C-r | sly-stickers-replay       | Replay sticker values                       |
| C-c I       | sly-inspect               | Eval an expression and inspect the result   |
| M-p / M-n   |                           | Navigate up/down in REPL                    |
|             |                           |                                             |

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


## SLIME Simple Commands {#slime-simple-commands}

| Keybinding  | Effect                                           |
|-------------|--------------------------------------------------|
| M-x slime   | Open the SLIME repl                              |
| C-c C-c     | Recompile a definition                           |
| C-M-x       | Evaluate expression and put result in minibuffer |
| C-c C-p     | Evaluate and pretty print the result             |
| C-c C-r     | Evaluate the selected region                     |
| C-c C-l     | Load a file into SLIME                           |
| C-c C-k     | Recompile and run file (Save first C-x C-s)      |
| **C-c C-z** | Go to SLIME REPL                                 |
| C-M-q       | Reindent s-expression                            |
| C-c M-q     | Reindent whole function                          |
| C-c C-u     | Undefine function                                |
| M-p M-n     | Navigate up/down in REPL                         |


## Geiser MIT REPL Keybindings {#geiser-mit-repl-keybindings}

This is for editing MIT Scheme files while reading SICP.

| Keybinding      | Command or Function or Definition       | Note                        |
|-----------------|-----------------------------------------|-----------------------------|
| M-x geiser      | geiser                                  | Open the Geiser REPL        |
| **C-c C-z**     | geiser-mode-switch-to-repl              | Go to Geiser REPL           |
| C-c C-a         | geiser-mode-switch-to-repl-and-enter    | Go to REPL and enter module |
| C-x C-e         | gieser-eval-last-sexp                   |                             |
| C-c C-c / C-M-x | geiser-eval-definition                  |                             |
| C-c C-r         | geiser-eval-region                      |                             |
| C-c C-b         | geiser-eval-buffer                      |                             |
| C-c C-k         | geiser-compile-current-buffer           |                             |
| C-c M-o         | geiser-repl-clear-buffer                | In REPL - clear             |
| M-p/n           | (Common) Previous and Next item in REPL |                             |
| C-c \\          | geiser-insert-lambda                    | Insert a lambda character   |

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


## Why use Functional Languages? {#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) {#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 {#other-resources}

-   [Learn X in Y mins: Common Lisp](https://learnxinyminutes.com/docs/common-lisp/)

[^fn:1]: This didn't last long, though I still plan to go through SICP.



> Thank you for reading!  
> Find more content at <https://manuals.ryanfleck.ca/>  
> Source page: <https://manuals.ryanfleck.ca/lisp/>  
> Site index: [llms.txt](https://manuals.ryanfleck.ca/llms.txt)