11
votes

Let us say I have a X.clojurescript and a X.clojure namespace. Everything in X.clojurescript is Clojurescript code, everything in X.clojure is Clojure code. Unfortunately, I cannot define macros directly in Clojurescript, I have to define them in Clojure and then bring them into a Clojurescript namespace using

(ns X.clojurescript.abc
  (:require-macros [X.clojure.def :as clj]))

This is fine. However, what if the macro (defined in X.clojure) is going to need to reference something defined in a Clojurescript namespace (X.clojurescript)? The problem is that the Clojure compiler does not look in my Clojurescript namespace (a separate directory) when resolving other namespaces.

I have gotten around this problem by simply creating a namespace in my Clojure code that has the same namespace and needed definition as exist in Clojurescript, but this seems kind of stupid. So, for instance, if I need X.clojurescript.abc.y in my macro, I will just create an additional namespace on the Clojure side that defs a dummy y in my Clojure version of X.clojurescript.abc; kind of dumb.

How do I deal with a macro that needs to refer to something on the Clojurescript side?

1
Make your macro such that it takes all the required things from clojurescript as parameter. If you could add some code it will be much easier to answer your sepcific query - Ankur
I don't think I understand your question. Your macro has to generate the code that will then be evaluated in clojurescript. So if you have to reference any clojurescript def wouldn't it be enough to generate the symbol in the expansion of the macro? - KIMA
refer to something on the Clojurescript side you need that at macro expansion time or this will be something that will be emitted in the output code? - Ankur

1 Answers

6
votes

The only time a macro needs a specific namespace at the time of definition is if the macro is using code from said namespace to generate the list of symbols it will return.

you can follow along with these examples in the repl:

(defmacro foo
  [a]
  `(bar/bar ~a))

the definition of foo will compile even though bar is not a defined namespace

(foo :a)

calling foo will now fail because you have not defined the bar namespace, or the function bar yet

(ns bar)
(defn bar
  [x]
  [x x])

defines bar in the bar namespace

(ns user)
(foo :a)

=> [:a :a]

Notice that bar does not need to exist at the time of foo's definition. In fact the namespace does not even need to exist at the time of foo's definition.