Consider Common Lisp, which satisfies both of those effects, because its debugger is a standard part
of the language and is also called at the point where the assertion fails, meaning there's no unwind
phase until the programmer specifically requests it; this is part of the error-handling model, even,
as a program effectively automates calling upon the restarts and the like otherwise called manually.
I believe Common Lisp would make a good addition to that ``Other Languages'' section of the article.
By the by, the ``OpenBSD has one less frame'' should instead become ``OpenBSD has one fewer frame''.
Thanks for the correction about less vs. fewer! I've pushed that fix.
> Consider Common Lisp, which satisfies both of those effects
I tried it in SBCL and it gave me an SB-KERNEL:ASSERT-ERROR stack frame on
top of the assertion. If I "list-locals" I get the local variables for
this system function, not my program. I have to go "down" a level before I
can start inspecting my own program.
CLISP is difficult to measure since the backtrace printer includes itself
when printing the backtrace, as well as the debugger REPL. If my program
isn't compiled, I have macro-expanded forms instead of stack frames, which
has absolutely terrible legibility. Though my local variables are in scope
and readily available. Compiled, I get stack frames but my variables are
not in scope, and I can't figure out how to inspect them.
CMUCL was like SBCL. There's a LISP::ASSERT-ERROR stack frame on top of my
program, so it fails my criteria. Worse, my test variables were optimized
out by default so I couldn't see all of them. I also couldn't directly
evaluate others because they looked too much like debugger commands (the
case for many single-letter variable names).
GCL has a CERROR stack frame when not compiled, but when compiled the
stack trace looks clean. In either case I could not figure out how to
inspect local variables, nor get any useful information from the debugger
other than the stack trace. This debugger seems as though it was written
to meet the technical requirements of the Common Lisp standard rather than
to be useful.
These were the four readily-available Common Lisp implementations, and
none meet my criteria. Ultimately debugging Common Lisp is a very poor
experience, especially compared to C and C++, and I'm glad I never need to
do it. The recursiveness of the debugger is neat in theory, but a disaster
in practice. I liked Common Lisp a long time ago, where I had hooked up to
Emacs and evaluated forms in buffers, and I even developed in Clojure
professionally for a time. Now that I'm more experienced, I can't stand
any of it. The ergonomics is so poor that I'd rather write programs in
assembly than any Lisp dialect.
By the by, I failed to earlier mention that I'd a similar experience with debuggers, at least within
other languages. I vowed a ways back to always use a debugger as opposed to lesser methods for ever
more; while GDB is easy enough, I never fully learned GNU APL's debugger; its REPL usually suffices.
> I tried it in SBCL and it gave me an SB-KERNEL:ASSERT-ERROR stack frame on top of the assertion.> If I "list-locals" I get the local variables for this system function, not my program. I have to> go "down" a level before I can start inspecting my own program.
I use SLIME so it's more convenient, but a mouse click to list local variables, and I don't see this
to be such a terrible issue, since it's useful information. It pales to previous Lisp environments,
sure, but it's still better than GDB; I can easily click and INSPECT any data structures in program.
> CMUCL was like SBCL. There's a LISP::ASSERT-ERROR stack frame on top of my program, so it fails my> criteria. Worse, my test variables were optimized out by default so I couldn't see all of them.
It may be necessary to DECLARE an OPTIMIZE for DEBUG, to avoid those variables being optimized away.
> Ultimately debugging Common Lisp is a very poor experience, especially compared to C and C++, and> I'm glad I never need to do it.
As with APL, an REPL usually suffices for most of for what one would want a debugger. Common Lisp's
debugger is for when a running program be interrupted or the like, and not for simple introspection.
So, it's often better to use INSPECT or DESCRIBE, like how I preferred strace over GDB for some Ada.
> Now that I'm more experienced, I can't stand any of it. The ergonomics is so poor that I'd rather> write programs in assembly than any Lisp dialect.
That seems extreme; I could mention my machine code work better than an assembler, but this sentence
suffices; I do agree that Lisp isn't the best programming language; all of them are damned by flaws.