For instance I have a macros in my-macros CLJ namespace (just a let macros copied from the clojure core) :
(ns my-macros)
(defmacro alt-let
[bindings & body]
(assert-args
(vector? bindings) "a vector for its binding"
(even? (count bindings)) "an even number of forms in binding vector")
`(let* ~(destructure bindings) ~@body))
I also have my-macros CLJS namespace that includes only:
(ns my-macros
(:require-macros [my-macros]))
This macros works fine when I use it in my clojurescript code this way:
No such namespace: clojure.lang.PersistentHashMap, could not locate clojure/lang/PersistentHashMap.cljs, clojure/lang/PersistentHashMap.cljc, or JavaScript source providing "clojure.lang.PersistentHashMap"
Use of undeclared Var clojure.lang.PersistentHashMap/create
Why do these errors occur and how to overcome this issue?
You are using the Clojure macro variants of let* and destructure since the macros run in Clojure and everything defaults to using clojure.core. Instead use the CLJS variant via cljs.core/destructure in the macro and everything should be fine.
I’ve tried rewriting CLJ namespace to CLJC like this:
(ns my-macros
(:require #?(:cljs [cljs.core :as cljs]))
#?(:cljs
(cljs/defmacro alt-let
[bindings & body]
(assert-args
(vector? bindings) "a vector for its binding"
(even? (count bindings)) "an even number of forms in binding vector")
`(cljs/let* ~(cljs/destructure bindings) ~@body))
:clj
(defmacro alt-let
[bindings & body]
(assert-args
(vector? bindings) "a vector for its binding"
(even? (count bindings)) "an even number of forms in binding vector")
`(let* ~(destructure bindings) ~@body))
This is not how macros work. Don’t use CLJC unless you really understand how macros work. I wrote a post explaining macros step by step, maybe that helps.
This should be about all you need (in a .clj) file.
(ns my-macros)
(defmacro alt-let
[bindings & body]
(assert-args
(vector? bindings) "a vector for its binding"
(even? (count bindings)) "an even number of forms in binding vector")
`(let* ~(cljs.core/destructure bindings) ~@body))
This doesn’t work too, I get the same errors. By the way, how is cljs/core namespace supposed to work if I want to use this macros in pure clojure? This is the reason I’ve tried to put this macros in a CLJC namespace.
If you want to write the macro in CLJC then the macro must live in the :clj portion of the code and the macro must check whether it is supposed to emit CLJS code or CLJ code. Using a reader-conditional to put a macro in :cljs does not work.
#?(:clj
(defmacro a-thing [& args]
(if (:ns &env) ;; this only exists when expanding CLJS code
`(cljs-code)
`(clj-code))))