> My usual experience with Clojure has been that the stack traces are long... but the exception error messages are generally pretty good, and the stack frames that correspond to user code generally have good information on the position of the offending statement.

I do not agree, but please note my comment isn't talking about "running" stack traces here it's talking about the compiler blowing up on what is essentially a syntax error:

(let [{:keys foo} {:foo 1}]
(print foo))

note how `foo` is bare rather than in a vector. Put that in a script, `clj -m` it

Exception in thread "main" java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol, compiling:(hello.clj:5:3)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6567)
at clojure.lang.Compiler.analyze(Compiler.java:6361)
at clojure.lang.Compiler.analyze(Compiler.java:6322)
at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5708)
at clojure.lang.Compiler$FnMethod.parse(Compiler.java:5139)
at clojure.lang.Compiler$FnExpr.parse(Compiler.java:3751)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6558)
at clojure.lang.Compiler.analyze(Compiler.java:6361)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6548)
at clojure.lang.Compiler.analyze(Compiler.java:6361)
at clojure.lang.Compiler.access$100(Compiler.java:37)
at clojure.lang.Compiler$DefExpr$Parser.parse(Compiler.java:529)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6560)
at clojure.lang.Compiler.analyze(Compiler.java:6361)
at clojure.lang.Compiler.analyze(Compiler.java:6322)
at clojure.lang.Compiler.eval(Compiler.java:6623)
at clojure.lang.Compiler.load(Compiler.java:7064)
at clojure.lang.RT.loadResourceScript(RT.java:370)
at clojure.lang.RT.loadResourceScript(RT.java:361)
at clojure.lang.RT.load(RT.java:440)
at clojure.lang.RT.load(RT.java:411)
at clojure.core$load$fn__5018.invoke(core.clj:5530)
at clojure.core$load.doInvoke(core.clj:5529)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:5336)
at clojure.core$load_lib$fn__4967.invoke(core.clj:5375)
at clojure.core$load_lib.doInvoke(core.clj:5374)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invoke(core.clj:619)
at clojure.core$load_libs.doInvoke(core.clj:5413)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invoke(core.clj:619)
at clojure.core$require.doInvoke(core.clj:5496)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.main$main_opt.invoke(main.clj:335)
at clojure.main$main.doInvoke(main.clj:440)
at clojure.lang.RestFn.invoke(RestFn.java:436)
at clojure.lang.Var.invoke(Var.java:423)
at clojure.lang.AFn.applyToHelper(AFn.java:167)
at clojure.lang.Var.applyTo(Var.java:532)
at clojure.main.main(main.java:37)
Caused by: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol
at clojure.lang.RT.seqFrom(RT.java:505)
at clojure.lang.RT.seq(RT.java:486)
at clojure.core$seq.invoke(core.clj:133)
at clojure.core$reduce1.invoke(core.clj:890)
at clojure.core$destructure$pb__4541$pmap__4544$fn__4547.invoke(core.clj:4013)
at clojure.core$reduce1.invoke(core.clj:896)
at clojure.core$destructure$pb__4541$pmap__4544.invoke(core.clj:4014)
at clojure.core$destructure$pb__4541.invoke(core.clj:4028)
at clojure.core$destructure$process_entry__4557.invoke(core.clj:4030)
at clojure.core$reduce1.invoke(core.clj:896)
at clojure.core$destructure.invoke(core.clj:4033)
at clojure.core$let.doInvoke(core.clj:4046)
at clojure.lang.RestFn.invoke(RestFn.java:467)
at clojure.lang.Var.invoke(Var.java:427)
at clojure.lang.AFn.applyToHelper(AFn.java:172)
at clojure.lang.Var.applyTo(Var.java:532)
at clojure.lang.Compiler.macroexpand1(Compiler.java:6468)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6546)
... 40 more

Yeah… the third time around you might instantly know what it is, the first time around when it's a few levels down a type method not so much.