If you are asking about learning metaprogramming as a paradigm I would rather suggest Racket. Lisps are famous for their metaprogramming capabilities and you have Clojure at the top of your list but writing macros are way easier in Racket than in Clojure. This is primarily because Racket IDE provides good debugging and tracing tools. Clojure is notorious for its cryptic error messages. This certainly doesn't help while you try to do code transformations. Once you learn the fundamentals you can apply them in (somewhat) more mainstream functional programming languages like Clojure or Rust.