Of course! It came to me in my sleep. The standard scheme
solution:
Possible fix #5: local methods
(def debugger (stack env)
(with (run t framenum 0 framecnt (1- (len stack)))
(def repl ()
(while run
(print)
(let it (read)
(if (is it 'q) (set run nil)
(is it 'u) (up)
(is it 'd) (down)
(is it 'f) (goto-frame (read))
(is it 'e) (eval-in (read))
(is it 'b) (backtrace)
(pr "Unknown command: " it)))))
(def print ()
(pr "\n" framenum ":\t" (car (nth framenum stack))))
...
(repl)))
This is even shorter because I don't need the outer environment
to hide the helper functions from the global environment. Duh!
Why didn't I see this sooner?
There we are, closures to the rescue :) Careful, though; remember that what you define with def will be accessible throughout the entire program. Use let or with for local functions. (I can't tell what you want there, but that's tripped people up on these fora before.)