Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I'm wondering what are some efficient ways to debug Common Lisp interactively using Emacs and SLIME.

What I did before: As someone who learned C and Python using IDEs (VS and PyCharm), I am used to setting break points, adding watches, and do stepping. But when I started to use CL I found the debugging workflow fundamentally different. I did not find good ways to set break points, step though lines and see how variables change.

The dumb method I used was adding "print" in code and run the code over and over again, which is very inefficient. I know we can "inspect" variables in SLIME but not sure how to do it interactively.

What I found: I came across this video on the development of a Morse code translator recently, and it shows a complete process of how to debug interactively in SLIME, which has been very informative and enlightening. It is as if we could "talk" to the compiler.

What I want: I searched online but found minimal tutorials demonstrating how an experienced Lisper actually develop and debug their programs. I am eager to learn such experiences.

  • How to debug interactively?
  • What are some good practices and tips? How to add breakpoint and step?
  • What shortcuts / tools / workflow do you use most frequently / find most useful when debugging?
like image 297
Jian Xu Avatar asked Jun 10 '16 18:06

Jian Xu


People also ask

Which debug feature is used to pause execution and examine variables?

Breakpoints are one of the most important debugging techniques in your developer's toolbox. You set breakpoints wherever you want to pause debugger execution. For example, you may want to see the state of code variables or look at the call stack at a certain breakpoint.

How do you run a lisp on slime?

Starting SLIMEIf you give a prefix argument ( C-u M-x slime ) then SLIME will prompt for the command to start Lisp (otherwise it uses inferior-lisp-program ). The server will listen for one connection from Emacs. To make that connection, use M-x slime-connect .


2 Answers

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.

like image 185
mobiuseng Avatar answered Oct 11 '22 14:10

mobiuseng


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.

like image 39
Torsten Anders Avatar answered Oct 11 '22 12:10

Torsten Anders