Could something be done about this? I tried to learn Clojure but I bumped into that fairly early on and gave up. Rust was way more approachable for me because good error messages form learning dialog between the learner and the language.
Could something be done about this? I tried to learn Clojure but I bumped into that fairly early on and gave up. Rust was way more approachable for me because good error messages form learning dialog between the learner and the language.
For those who don't know, Clojure's error messages... aren't. They take the form of a stack trace from the compiler's internals, and that whole stack trace just gets barfed out onto the terminal. There's an exception message but it sometimes just isn't that helpful.
I know there was an effort a while back to improve the situation, but last I saw (2019) I believe things were only marginally improved. It's a shame because other than that it's really quite a fantastic language.
user=> (defn foo [[a b] (+ a b))
Syntax error reading source at (REPL:14:26).
Unmatched delimiter: )
user=> (defn foo [a b] a/b)
Syntax error compiling at (REPL:1:1).
No such namespace: a
user=>
It will give you a stack trace of the compiler when asked following a syntax error though, with a disclaimer not to confuse it with your own code: user=> (pst)
Note: The following stack trace applies to the reader or compiler, your code was not executed.
CompilerException Syntax error compiling at (1:1). #:clojure.error{:phase :compile-syntax-check, :line 1, :column 1, :source "NO_SOURCE_PATH"}
clojure.lang.Compiler.analyze (Compiler.java:6808)
clojure.lang.Compiler.analyze (Compiler.java:6745)
[...]
Possibly you were using tooling that always tried to present the stack trace without discerning between kinds of evaluation errors?And the move to spec, ugh, UGH. I have wasted so much of my life looking at spec errors for (e.g.) namespace declarations and being completely unable to tell what was wrong. I don't know how to fix this, unfortunately.
An REPL that is integrated with your editor is key.
A good linter such as clj-kondo (comes with Calva on VSCode), helps a lot to avoid typing errors and a lot more.
Using a REPL middleware which visualizes your output such as portal is very nice.
One issue is when you get errors that involve anonymous closures. It might be harder to navigate those errors. But I don't know of a language that does this well. Clojure makes it very easy to divide and conquer though.
Another big one involves macros. Macros are powerful, but errors you get from them can be quite cryptic in some cases. Usually for common macros there are linter rules that you can use/find to avoid those.
Clojure itself has a symbiotic relationship with nils. However as soon as you interact with Java data structures you might run into exceptions here. It's something to be wary of.
Finally, spec and malli give you tools to adorn your code with little specifications to state your assumptions and guarantees. You can automatically run those while you're writing code to get sharp, human readable error messages.
So yes, Clojure error messages can be scary/confusing at times, even though it has gotten better. But there are a lot of things you can do, or have been done for you that really help here and sometimes go quite a bit beyond of what you'd expect from a more mainstream language.