screwlisp proposes kittens

Steel bank common lisp, slime and save-lisp-and-die and not being ahistorical

A point of confusion about lisp useage is this: In the most popular lisp compiler, sbcl, saving and quitting are done in one action: This produces a .core file, and you pick up again by loading the core which is literally the place you issued sb-ext:save-lisp-and-die. This is consciously similar to cold booting into your lispmachine universe (memory band). You don’t have to recreate the state you left off, because that state itself was literally what you saved.

Now the problem is that we almost always use lisp with slime, or something like it. Slime in emacs, lem or vim provides stuff like autocompletion, displaying where-you-are in a function’s argument list that you are currently writing, an interface into lisp’s debugging protocol and so forth. The problem is that the default way to use slime starts a background thread in your lisp image serving the swank wire protocol server that slime talks to your running lisp images over. But sb-ext:save-lisp-and-die doesn’t know how to save an image running multiple threads (which is the default, with slime)!

A simple way / example

I am assuming you read my starting-out-with-lisp article and have eev mode in emacs!

Eepitch-shell.

• (eepitch-shell)

Remembering that tapping F8 on a red star line in emacs evals some emacs lisp

Explicitly sbcl in that shell

and otherwise sends the line to your eepitch target buffer.

cd

sbcl

Explicitly start the swank server in that sbcl

(merge-pathnames #P"~/.emacs.d/slime/" #P"start-swank.lisp")

(load *)

remembering that * means ‘the last first value’.

* (merge-pathnames #P"~/.emacs.d/slime/" #P"start-swank.lisp")
#P"~/.emacs.d/slime/start-swank.lisp"
* (load *)
WARNING:
   redefining EMACS-INSPECT (#<SB-PCL:SYSTEM-CLASS COMMON-LISP:T>) in DEFMETHOD
;; Swank started at port: 4005.
T
* 

So, we have a background thread serving swank for our slime to slime-connect to.

slime-connect to that swank server

• (slime-connect "localhost" 4005)

; SLIME 2.29.1
CL-USER>

Hacks and glory await!

This is where we basically always use lisp from. It’s got everything (and it has always had everything). Here is slime’s documentation about slime.

Do something in there

• (setq eepitch-buffer-name "*slime-repl sbcl*")

(let ((count 0)) (lambda () (incf count)))

(funcall *)

(defparameter *counter* **)

(funcall *counter*)

Let’s disconnect.

• (slime-disconnect)

Let’s go back to the shell sbcl is running in and save. slime-disconnect’s default already stopped the server, whose threads get cleaned up by default.

• (eepitch-shell)

(sb-ext:save-lisp-and-die #p"foo.core")

Let’s reconnect

sbcl --core foo.core

(merge-pathnames #P"~/.emacs.d/slime/" #P"start-swank.lisp")

(load *)

• (slime-connect "localhost" 4005)

CL-USER> (funcall *counter*)
3

and we’re back!

Conclusion

We saw that we can use the most popular lisp compiler, sbcl with slime in emacs with its sb-ext:save-lisp-and-die to save a core - literally our current image - and then load the core with sbcl --core foo.core where we saw our closure that we made in the lisp image still had the state we left it in.

It is ahistorical to not have a persisted memory band universe between sessions on the lisp machines for example. It’s not good enough to hope that in modern times, humans got really good at juggling text serialisations by hand - we are actually still bad at that. We still want and benefit from these futuristic features.

Fin.

Talk on the Mastodon as always please

I think some people do either end up not using slime, or not using sbcl’s ext:save-lisp-and-die to save and resume their universe lisp image core when they are using slime. When you should.

screwlisp proposes kittens