# Need help with writing macros for ClojureScript

**URL:** https://clojureverse.org/t/need-help-with-writing-macros-for-clojurescript/6671
**Category:** Beginners
**Tags:** macros, clojurescript
**Created:** [October 11, 2020, 9:41pm UTC](https://clojureverse.org/t/need-help-with-writing-macros-for-clojurescript/6671 "2020-10-11T21:41:43Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![u473t8](https://clojureverse.org/user_avatar/clojureverse.org/u473t8/32/3259_2.png) [@u473t8](https://clojureverse.org/u/u473t8)
#### Post date: [October 11, 2020, 9:41pm UTC](https://clojureverse.org/t/need-help-with-writing-macros-for-clojurescript/6671/1 "2020-10-11T21:41:43Z")

</div>

For instance I have a macros in `my-macros` CLJ namespace (just a `let` macros copied from the clojure core) :

```auto
(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:

```auto
(ns my-macros
  (:require-macros [my-macros]))

```

This macros works fine when I use it in my clojurescript code this way:

```auto
(ns my-namespace
   (:require [my-macros :refer-macros [alt-let]])) 

(alt-let [[a b] [1 2]]
  (js/console.log (+ a b)))

```

But if I try to do associative destructuring I get following errors:

```auto
(alt-let [{:keys [a b]} {:a 1 :b 2}]
  (js/console.log (+ a b)))

```

```auto
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?

---

<div class="post-metadata">

### Author: ![jiyinyiyong](https://clojureverse.org/user_avatar/clojureverse.org/jiyinyiyong/32/85_2.png) [@jiyinyiyong](https://clojureverse.org/u/jiyinyiyong)
#### Post date: [October 12, 2020, 3:29am UTC](https://clojureverse.org/t/need-help-with-writing-macros-for-clojurescript/6671/2 "2020-10-12T03:29:01Z")

</div>

looks strange, where did the identifier `create` come from?

---

<div class="post-metadata">

### Author: ![thheller](https://clojureverse.org/user_avatar/clojureverse.org/thheller/32/534_2.png) [@thheller](https://clojureverse.org/u/thheller)
#### Post date: [October 12, 2020, 8:07am UTC](https://clojureverse.org/t/need-help-with-writing-macros-for-clojurescript/6671/3 "2020-10-12T08:07:18Z")

</div>

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.

---

<div class="post-metadata">

### Author: ![u473t8](https://clojureverse.org/user_avatar/clojureverse.org/u473t8/32/3259_2.png) [@u473t8](https://clojureverse.org/u/u473t8)
#### Post date: [October 12, 2020, 8:53am UTC](https://clojureverse.org/t/need-help-with-writing-macros-for-clojurescript/6671/4 "2020-10-12T08:53:32Z")

</div>

I’ve tried rewriting CLJ namespace to CLJC like this:

```auto
(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))

```

but I still get the same errors.

---

<div class="post-metadata">

### Author: ![thheller](https://clojureverse.org/user_avatar/clojureverse.org/thheller/32/534_2.png) [@thheller](https://clojureverse.org/u/thheller)
#### Post date: [October 12, 2020, 10:42am UTC](https://clojureverse.org/t/need-help-with-writing-macros-for-clojurescript/6671/5 "2020-10-12T10:42:22Z")

</div>

This is not how macros work. Don’t use CLJC unless you really understand how macros work. I wrote a [post](https://code.thheller.com/blog/shadow-cljs/2019/10/12/clojurescript-macros.html) explaining macros step by step, maybe that helps.

This should be about all you need (in a `.clj`) file.

```auto
(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))

```

---

<div class="post-metadata">

### Author: ![u473t8](https://clojureverse.org/user_avatar/clojureverse.org/u473t8/32/3259_2.png) [@u473t8](https://clojureverse.org/u/u473t8)
#### Post date: [October 12, 2020, 12:05pm UTC](https://clojureverse.org/t/need-help-with-writing-macros-for-clojurescript/6671/6 "2020-10-12T12:05:40Z")

</div>

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.

---

<div class="post-metadata">

### Author: ![thheller](https://clojureverse.org/user_avatar/clojureverse.org/thheller/32/534_2.png) [@thheller](https://clojureverse.org/u/thheller)
#### Post date: [October 12, 2020, 1:04pm UTC](https://clojureverse.org/t/need-help-with-writing-macros-for-clojurescript/6671/7 "2020-10-12T13:04:29Z")

</div>

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.

```clojure
#?(:clj
   (defmacro a-thing [& args]
     (if (:ns &env) ;; this only exists when expanding CLJS code
       `(cljs-code)
       `(clj-code))))

```

---

<div class="post-metadata">

### Author: ![system](https://clojureverse.org/uploads/default/original/2X/5/51079bf9e4b7d9466242c06cf1e43b9f8bd6da14.png) [@system](https://clojureverse.org/u/system)
#### Post date: [April 13, 2021, 1:04am UTC](https://clojureverse.org/t/need-help-with-writing-macros-for-clojurescript/6671/8 "2021-04-13T01:04:34Z")

</div>

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.
