Common Lisp step-by-step debugging with SBCL and SLIME
12:50 14 Nov 2025

I tried to debug the function below (find-3rd-largest), and wanted to execute expressions step by step from (break), as I did for other programming languages. So, I compiled the function with C-u C-c C-c (C-u M-x slime-compile-defun), C-M-x (slime-eval-defun) or C-c C-k (slime-compile-and-load-file), and executed (find-3rd-largest '(2 1 0 6 5 3 4)) in REPL. As I expected, the REPL stopped and sldb started, where I could type x (sldb-next) or s (sldb-step). However, sldb is finished after typing x or s at most 2~3 times without further traversing.

I'm wondering whether step-by-step debugging is not possible for some code. I tested with "SBCL 2.5.10.roswell" and "SBCL 2.1.11.debian".

(defun find-3rd-largest (nums)
  ;; [Skippable Note]
  ;; This is a function that is identical with the "nthmost" macro in the book "On Lisp"
  ;; when finding the 3rd largest value.
  ;; ( https://github.com/DalekBaldwin/on-lisp/blob/276576e17d3a6ae945f85e39a5489e22e2cd3d68/src/chapter-13.lisp#L29 )
  ;;
  ;; The following expressions make the same result
  ;; > (find-3rd-largest '(2 1 0 6 5 3 4))
  ;; 4
  ;; > (nthmost 2 '(2 1 0 6 5 3 4))  ; 2 means the index 2 and the 3rd largest item.
  ;; 4

  (declare (optimize (speed 0) (safety 3) (space 0) (debug 3)))

  (let ((g7 nums)
        (g1 nil) (g2 nil) (g3 nil))
    (unless (< (length g7) 3)
      (break)
      (let ((g6 (pop g7)))
        (setq g1 g6))
      (let ((g5 (pop g7)))
        (if (> g5 g1)
            (setq g2 g1 g1 g5)
            (setq g2 g5)))
      (let ((g4 (pop g7)))
        (if (> g4 g1)
            (setq g3 g2 g2 g1 g1 g4)
            (if (> g4 g2)
                (setq g3 g2 g2 g4)
                (setq g3 g4))))
      (dolist (g8 g7)
        (if (> g8 g1)
            (setq g3 g2 g2 g1 g1 g8)
            (if (> g8 g2)
                (setq g3 g2 g2 g8)
                (if (> g8 g3)
                    (setq g3 g8)
                    nil))))
      g3)))
common-lisp sbcl slime