Suppose we use SBCL's #'save-lisp-and-die to create an server applicatioon App1, which works very well. Now we want to replace a function #'func1 with a new version without stopping App1. How can we do it in Common Lisp ?
Any suggestion is appreciated !
You need to load the new function definition. Then new function will be available immediately; code will call newly loaded function.
New function definition may be loaded in many ways:
(load (compile-file "file.lisp"))
where file.lisp
is a source code for function
(load "file.fasl")
where file.fasl
is compiled source code
(eval (defun ...))
Of course, there are exceptions and complications:
- This will not replace already running calls of previous functions; for example, an infinite event loop can not be changed this way - it will have to support some kind of stopping and calling a new function. However, such long-running functions are rare. It can be worked around by using recursion instead of looping (but not all compilers do tail-call optimization).
- If you somewhere grabbed a pointer to function (for example, by
(function FOO)
where FOO
is the name of a function), it will retain its old value. To avoid this, use symbols instead of function pointers (symbols are funcall
able).
- The code of a function is a subject to garbage collection. You should be careful not to leave references to old versions of a function lying around. Also, if some functions become not needed, you should not forget to
fmakunbound
their symbols.
- If the function was used at compile time, all of the affected code should also be reloaded
- If you had high levels of optimization (which is not by default), compiler might have inlined the function into others. CLHS discriminates the cases when redefining a function becomes «undefined behavior».
But in practice, code reloading works well in most Common Lisp implementations.
I personally ensure that SWANK (the server part of SLIME) is running, so that I can connect to the image at any time with Emacs+SLIME and redefine whatever I want.
(ql:quickload "swank")
(swank:start-server :port 1234) ;; listen for SLIME connections on port 1234
Then in Emacs, you can M-x slime-connect
, and follow the prompts.
If you don’t want to do this for whatever reason, your implementation might offer something specific.