I agree with this. The error messages in most Common Lisp environments are just so much better than you get in languages like Clojure or C# or Python.
I even have a good example to illustrate this. A while back someone had emailed me because he was trying to implement a terrain generation algorithm called Diamond Square, which I had written a blog post about. It was mostly working, but would crash with an IndexOutOfRangeException at one point. He had tried debugging it and emailed me to see if I could point him in the right direction.
Getting an array out of bounds exception didn't surprise me, because in Diamond Square the algorithm will try to read outside of the bounds of the array by default -- part of implementing the algorithm correctly is detecting that case and making sure to handle it, either by just ignoring that cell or by wrapping it around to the other side of the array. So I assumed he had just forgotten to do this. But then I read his code, and no, he had definitely added a check for `if (x >= array.length)`.
This code was using Unity, so it was written in C#, but the point applies to most languages. Look at the errors given back by C# and Clojure for this problem:
user=> (nth [:a :b :c] x)
IndexOutOfBoundsException clojure.lang.PersistentVector.arrayFor (PersistentVector.java:153)
float[] fs = new float[5];
Console.WriteLine(fs[x]);
Unhandled Exception:
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at MainClass.Main (System.String[] args) [0x00009] in <fdc0f271de194e269b9b6c61b644f47b>:0
I went down the rabbit hole trying to figure out how he could possibly be indexing into his array and missing the bounds check. It took my brain hours to untwist itself and see the answer, which came to me in a flash as I was trying to fall asleep. Have you figured it out yet? Here's what Common Lisp would have told me for this error:
[SBCL] CL-USER> (aref #(:a :b :c) *x*)
debugger invoked on a SB-INT:INVALID-ARRAY-INDEX-ERROR in thread
#<THREAD "main thread" RUNNING {10005505B3}>:
Invalid index -1 for (SIMPLE-VECTOR 3), should be a non-negative integer below 3.
Well there's the problem! He had added the check to make sure the index didn't go past the end of the array, but the algorithm also tries to reach past the left side of the array too! I replied, he added the check for `x < 0` and everything was fixed.
If I had been able to get this running in a debugger I probably could have figured it out, sure. But Common Lisp's nice error messages made that unnecessary -- instead of telling me "You tried to access an invalid index" it says "You tried to access X, but I was expecting Y". It's so much nicer, and in a lot of cases (like this one) instantly makes the error completely obvious.
I don't know exactly why Common Lisp's error messages tend to be so much better than most other dynamic languages. Maybe it's a culture of good error writing from the very start. Maybe it's because the language itself makes it easy to provide good messages, thanks to things like CHECK-TYPE, ECASE, ETYPECASE, etc (and their `C` variants, which is a whole extra layer of goodness on top of all that). I don't know. I just know that hitting an error in most languages feels like hitting a brick wall (especially in JVM languages, good god are those stack traces awful) but in Common Lisp it feels like the system is at least trying to do its best to help me.
I even have a good example to illustrate this. A while back someone had emailed me because he was trying to implement a terrain generation algorithm called Diamond Square, which I had written a blog post about. It was mostly working, but would crash with an IndexOutOfRangeException at one point. He had tried debugging it and emailed me to see if I could point him in the right direction.
Getting an array out of bounds exception didn't surprise me, because in Diamond Square the algorithm will try to read outside of the bounds of the array by default -- part of implementing the algorithm correctly is detecting that case and making sure to handle it, either by just ignoring that cell or by wrapping it around to the other side of the array. So I assumed he had just forgotten to do this. But then I read his code, and no, he had definitely added a check for `if (x >= array.length)`.
This code was using Unity, so it was written in C#, but the point applies to most languages. Look at the errors given back by C# and Clojure for this problem:
I went down the rabbit hole trying to figure out how he could possibly be indexing into his array and missing the bounds check. It took my brain hours to untwist itself and see the answer, which came to me in a flash as I was trying to fall asleep. Have you figured it out yet? Here's what Common Lisp would have told me for this error: Well there's the problem! He had added the check to make sure the index didn't go past the end of the array, but the algorithm also tries to reach past the left side of the array too! I replied, he added the check for `x < 0` and everything was fixed.If I had been able to get this running in a debugger I probably could have figured it out, sure. But Common Lisp's nice error messages made that unnecessary -- instead of telling me "You tried to access an invalid index" it says "You tried to access X, but I was expecting Y". It's so much nicer, and in a lot of cases (like this one) instantly makes the error completely obvious.
I don't know exactly why Common Lisp's error messages tend to be so much better than most other dynamic languages. Maybe it's a culture of good error writing from the very start. Maybe it's because the language itself makes it easy to provide good messages, thanks to things like CHECK-TYPE, ECASE, ETYPECASE, etc (and their `C` variants, which is a whole extra layer of goodness on top of all that). I don't know. I just know that hitting an error in most languages feels like hitting a brick wall (especially in JVM languages, good god are those stack traces awful) but in Common Lisp it feels like the system is at least trying to do its best to help me.