I would say I mostly have trouble with reading and understanding Clojure code quickly, coming up with Clojure idiomatic solutions, and editing it.
I think it helps to break down Clojure into three categories:
- (Pure-ish) Functional Programming
I know a lot of people, it takes them a while for this paradigm to click. Because you are often tempted to organize things as classes and objects, or interfaces and methods. And it’s also hard to figure out how to perform operations when you can’t do imperative loops, and if/else branches, and all that.
I would go read on that, and practice exercises here: https://4clojure.oxal.org/
Once you know how to perform operations using map/reduce and recursion, without mutable state, and have learned about the higher order functions like filter, remove, partition, group-by, juxt, fnil, and all that, it should start to click.
Also, learning how to structure code functionally, how to manage state, side effects, break things down in an Onion/Clean architectural style, model entities with functions that operate on them but without classes and objects and all that. I’m not sure of a good resource here though.
- Interactive Programming
You start the program with an empty template, and you build it up as you go, loading code in one function at a time, reloading as you iterate on each function, etc. All from inside your IDE, connected to live resources the app will be using, etc.
Getting used to REPL-driven-development basically.
Again, I’m not sure of good resources. But this is another aspect that should eventually “click”.
- Lisp
Figuring out how it’s all based on very simple syntax and initial rules, and it builds up to complex semantics through macros. Getting to read code bottom up, and inside out. Learning how to navigate and edit s-expressions quickly using semantic editing. Learning how you can create new syntax and new semantics to help you get rid of verbosity and repetition in your code by adding macros, or producing data based DSLs. The latter should make you learn about homoiconicity and why that makes things easier to inspect, and helps with building DSLs both data-driven or macro based.
This should also eventually “click”.
Those three things are orthogonal, but come together nicely. They each take their own getting used too and “ah ha!” moment though. I think it’s easier to tackle them one at a time.