Here's another +1 for even better error message out of the box.
The libraries mentioned below are treating the symptoms more or less successfully, but let's look at it from the point of someone wanting to learn Clojure, hence heads to Clojure.org, clicks on Getting Started.
Ok, I now know how to download it. Maybe I'll try to get a feel for it by using
Now I have the bare bones experience (with the - according to clojure.org confusing error messages) (see : "One confusing error you might see is the result of accidentally trying to evaluate a list of data as if it were code:" )
Well, let's go to Learn Clojure first.
Ok, still nothing about how to launch a REPL.
Third link: Good idea to start a REPL.
Fourth link: Here are the n ways to start a REPL.
Here are other ways to run a REPL.
None mention anything about: If you are a beginner, let's add clj-stacktrace, then start a REPL.
Do you see why this is impractical?
I know you have put a lot of effort into better docs in recent years and I feel bad pointing out these things. It is hard coming back to something so familiar and look at it through the eyes of a developer who wants to learn about this new language.
I believe you have 1 or maybe 2 shots at making a good impressions and readable error messages that tell you where you went wrong is an important part of that.
user=> (map 1 inc)
Don't know how to create ISeq from: clojure.core$inc:
user=> (1 2 3)
Execution error (ClassCastException) at user/eval7 (REPL:1). class java.lang.Long cannot be cast to class clojure.lang.IFn (java.lang.Long is in module java.base of loader 'bootstrap'; clojure.lang.IFn is in unnamed module of loader 'app')
Both don't tell me what I did wrong. It tells me some specifics of how the lisp evaluator works behind the scenes. (some of them are documented on clojure.org).
Since none of this is helpful for me, the new user, I'm going to google it.
The tolerance for googling error messages for errors like wrong argument order or invoking something that can't be invoked, is not very high for beginners.
That is where you leave the impression that error messages guiding the user are not important.
(btw, curiously, you are already handing (nil 2 3) pretty good and not throwing an NPE)
This is where clojure (the implementation) actively contributes to the 'huge learning curve' meme.
It doesn't matter that - after seeing this error often enough - I learned what it is. (with regards to Sean's comment).
The damage is done.
Other Clojure dialects are doing a better job here. (CLJS and Sci, for example).
Speaking of effort: There's an objection that providing better error messages would impact performance. If we are talking about exception handling here (and in both cases above we do),
I'm not sure I understand where the performance impact is.
Exception handling because an s-expr fails is not on the performance-critical path, I would think.
Happy to better understand where the performance aspect comes into play.
Also, just for the two sample error messages above, the effort to write them from the perspective of the user - not the system - is not very high. For one of them it means changing line 557 in RT.java
Better error messages might mean catching lower-level exceptions, associating them with the current AST and re-throwing them with a message associated with the list element that generated the error.
I would implore you to guide beginners to the very best REPL they can get.
Make that the default in Getting Started and Learning Clojure.
Then you can draw back the curtain and say: Ya know, underneath is IFn and ISeq and you might see Java stacktraces.
There are so many new concepts to learn and understand when going down the Clojure path. Re-interpreting error messages shouldn't be one of them.