What are efficient ways to debug Common Lisp in Emacs and SLIME?

With Common Lisp and Slime you can set break points, look at the values of variables, use an inspector for looking at composite data structures including class instances, and step through your code -- all in principle rather similar to what you are used with IDEs like PyCharm. Rainer Joswig's video Debugging CL-HTTP, using Clozure Common Lisp, GNU Emacs and SLIME (https://vimeo.com/77004324) demonstrates all these features, so you can see how it is done in practice with Slime.

One feature I actually greatly prefer in Common Lisp + Slime over debugging with PyCharm is that in the former you can run your program normally and automatically enter the debugger directly at an error and the debugger by default stops where an uncaught exception was raised. By contrast, with PyCharm you run your program, run into an error, then start your program again with the debugger and set manually your breakpoints or ask PyCharm to break at any exception. PyCharm currently does not support to automatically break only at an uncaught exception.


There is a number of things you can do:

  • You can trace a function call (see TRACE and UNTRACE in Common Lisp or slime-toggle-trace-fdefinition*). This helps with recursive calls: you can see what you pass and what they return at each level.
  • Standard thing: add (format t ...) in places. I guess, no need to comment.
  • If the code breaks, you will get into debugger. From there you can examine the stack, see what was called and what arguments were passed. See @jkiiski link: it has really great information about it, including (break) form that will act as a breakpoint and get you to debugger. Spoiler alert: you can change the values in the inspector, you can change and re-compile your code and restart from (almost) any place in the stack.
  • Last but not least: to debug macros, you will need slime-macroexpand-1 (wrapper over MACROEXPAND-1) and even better C-c M-e for macro stepper.

One last advice: if you are to do a serious debugging, include (declaim (optimize (debug 3))) in your file, otherwise some CL implementations have a tendency to optimize away the calls on the stack or make arguments inaccessible.