I think Clojure is wonderful as a first language. That's an easy thing to say and hard to back up though — Clojure wasn't my first language, and I knew Java before I started learning Clojure.
I think programming in general has a pretty steep learning curve because there is a very comlpex mapping from code in the text file to the behavior of the program when it's executed. As a software developer, you need to have a virtual machine in your head that can execute the code while you write it. The longer the feedback loop from writing code to seeing its execution results, the bigger the load on your mental virtual machine, the harder it is to progress. Other mainstream programming languages try to solve this problem with type systems and IDEs, and I think they are not good enough at that, because:
- type systems introduce complexity and require you to always write code that is about types and not about your problem;
- type systems are rudimentary, they only check what can be expressed in types, so they can only help with how things shouldn't be combined (e.g. they prevent you from summing string with number), but not with how your code behaves when executed (e.g. they can't prevent you from adding value to the end of a list when you wanted to add to the beginning).
Type systems get more and more complex to help you with writing correct code. You can have a look how Idris promotes type-driven development that helps with writing matrix transposition: https://youtu.be/mOtKD7ml0NU?t=1607
Here is a type signature for matrix transposition in Idris, without any implementation:
transpose : Vect n (Vect m a) -> Vect m (Vect n a)
I think it's nice that the language can help you fill in the blanks when you want to transpose a matrix, but what if you had a language that allows to have the actual implementation shorter then this signature?
(defn transpose [xs] (apply mapv vector xs))
What if you could immediately try this particular piece of code and see how it behaves?
(transpose [[1 2] [3 4]])
=> [[1 3] [2 4]]
In the end, we want to write code that makes computer behave the way we want it to behave. I think seeing the result of code execution immediately as you wrote it is a better way to validate the behavior than writing code in 2 languages in the same file, where one rudimentary language is for a compiler to have a dialog with you (type signatures), and another is for a computer to execute (function calls). Less noise, less cognitive load, more focus on a problem, faster and more useful feedback = wonderful first language, I think :)
P.S. I could go on about data processing with maps and generic functions vs classes and methods, but I don't have time right now. Much more simple and concise in Clojure!