Lisp is daunting partly because of the alien syntax, but mostly because there are all these new tools you have to pick up and learn before you can play.

What grinds your progress to a halt in particular is configuring the code editor. Lisp is appreciated for its interactive "image-based" development experience where you flesh out programs a little bit at a time by talking to a listener, also called an interpreter or a REPL (Read-Eval-Print Loop). Think Python but much better.

Specially-tailored code editors make this conversation with Lisp seamless, so should you dive into emacs+SLIME, or stick with vim and invest time in a plugin that feels rough around the edges? Neither! Let's get started in Lisp with vanilla vim in 10 minutes.

Get a Lisp

While Lisp comes in many flavors I suggest Common Lisp as a starting point. Common Lisp is specified as an ANSI standard, many great books are written in it and there are numerous implementations to choose from.

You can think of the implementation as your compiler, although in the Lisp world it provides a lot more. SBCL (Steel Bank Common Lisp) is one such implementation.

Install it with your package manager (example for Ubuntu/Debian):

apt-get install sbcl

Or download a binary: SBCL Downloads page (remember to check its integrity).

Pre-flight with the SBCL Listener

Running sbcl in the terminal should now greet you with:

This is SBCL 2.3.9, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.

SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses.  See the CREDITS and COPYING files in the
distribution for more information.
*

The asterisk at the end begs you to start typing some Lisp expressions:

(* (+ 2 4) (- 9 2))
(car (list 1 2 3))
(cdr (list 1 2 3))

For convenience, run SBCL with rlwrap. This grants you better hotkeys such as Alt-arrows to navigate words, Alt-backspace to remove words, Up/Down arrows to navigate line history.

rlwrap sbcl

When entering code with errors such as mismatched parentheses SBCL will give you an informative message before stepping into the debugger. Debugging and restarting in Lisp is more than we can chew, for now we need an easy exit:

(print "Oh no!"))
;; Produces an error due to mismatched parentheses.
;; Type this to exit debugger:
top

Top is short for "exit debugger and return to top-level REPL". When in doubt, top.

Get a Vim

Terminal and Code split

Open "foo.lisp" in vim (recent vim or neovim) and run:

:vsplit
:terminal

OR 

:vert term

Ctrl-w w or Ctrl-w Ctrl-w to switch between terminal and code buffer.

Fix Insert/Normal mode switch

Notice how you are stuck in "Insert" mode when in the terminal buffer, lovely! Inside terminals there is a special vim keybind for "Normal" mode: Ctrl-w N (capital N). Neovim prefers Ctrl-\ Ctrl-n for some reason. Forget both and bind Escape:

   .vimrc config:
:tnoremap <Esc> <C-w>N

   neovim lua config:
vim.keymap.set('t', '<Esc>', '<C-\\><C-n>')

Macros (the vim kind)

Wouldn't it be nice if we could write Lisp expressions in the first window and send them over to a running SBCL listener in the terminal window? Let's automate that workflow with vim macros.

Setup

  • Open a terminal inside vim as in the previous section.
  • In that terminal, run rlwrap sbcl.
  • Test that you can switch between Normal / Insert mode using Escape key.
  • Switch back to your "code" buffer with Ctrl-w w.
  • Write a valid Common Lisp expression such as (print "Hello world!").

@r -- run paragraph

  • Switch to code buffer, press Escape to enter Normal mode.
  • Move cursor inside a valid expression.
  • Press q, r. Vim shows "recording @r".
  • Press v, a, p. This creates a Visual selection Around Paragraph (VAP).
  • Press y to yank (copy) text.
  • Ctrl-w w to switch window.
  • Ctrl-w "" to enter yanked text. (neovim users can use p instead).
  • Ctrl-w w to switch window.
  • Press q. The macro is now recorded!
  • To use the macro, hover an expression in normal mode and press @, r.

This macro is perfect for running bags of expressions such as a function definition followed by test cases:

(defun square (x)
  (* x x))
(square 4)
(square 5)

@t -- top, exit debugger

  • Switch to code buffer, press Escape to enter Normal mode.
  • Press q, t. Vim shows "recording @t".
  • Press Ctrl-w w to switch window.
  • Type top and press Enter.
  • Press Ctrl-w w to switch window.
  • Press q. The macro is now recorded!
  • To use new macro, in normal mode press @, t.

You can run code @r and recover from errors with @t.

Read and experiment

Congratulations, you now have a primitive "REPL"! Lisp is immediately within reach.

The two macros @r and @t are enough to follow along introductory books and play with code snippets. It is janky and sometimes you have to force @t multiple times for it to stick... but you can poke at the interpreter.

Try balancing parentheses manually at first. If it feels like too much work, a lot of people swear by using plugins to balance them automatically such as paredit. This enables a structured editing of expressions though it requires having additional keybinds to merge expressions, "slurp" and "barf" (yes that's a thing) and so on.

As you make progress you can decide whether to jump over to Emacs + SLIME/SLY or stick with Vim + SLIMV/VLIME.

To begin your journey here are some books from beginner to advanced. The authors kindly offer them as free download, and they are available in print.