1

I have a code-base for a graphics program in cljx that gets compiled to Clojure and ClojureScript.

I now want to introduce my first macro.

(defmacro optional-styled-primitive [args body] 
   (let [extra (conj args 'style)] 
     `(fn (~extra (->SShape ~'style ~body))
          (~args (->SShape {} ~body)) 
      )
   )
)

The purpose of this macro is to take a list of arguments, and an expression that uses those arguments to generate a geometry. And to return a function with two arities : one of which takes an optional style parameter. This macro is then to be used within the file where it's defined, to make a number of other functions that optionally take styles. For example :

(def square (optional-styled-primitive [n] [[0 0] [0 n] [n n] [n 0]]))

But introducing this macro, obviously, breaks the ClojureScript stage of the compilation.

What I can't figure out is what to do about it. The online discussions talk about ClojureScript needing to use :require-macros but I never actually export or require this macro anywhere. I just want to use it where it's defined. So how can I, in the middle of a file, tell the compiler to use Clojure to expand this macro, before it gets to the ClojureScript compiler?

interstar
  • 26,048
  • 36
  • 112
  • 180
  • `defmacro` is what tells the compiler to expand the macro before compiling the rest of the code. Even in Clojurescript, you should be able to just write `defmacro` and then use the macro. I suspect something else is going on here. – skillet-thief Sep 02 '14 at 07:42

1 Answers1

0

OK.

I've made some progress with this.

Here's what I did.

1) I refactored my macro definition out into a separate file called macros.cljx

2) In the file where I was using the macros, I did this. (A different require for clj and cljs)

(#+clj :require #+cljs :require-macros 
     [myapp.macros :refer [optional-styled-primitive]])

3) I updated my leiningen project.clj file :

:cljsbuild {:builds [{
     :source-paths ["target/classes" "src-cljs" ] ...

The important thing here I added "target/classes", which is the output-path where cljx puts the clj files it creates, to the cljsbuild source-paths. This is where the cljsbuild process can find the clj file with the macro definition.

I'm not sure if this is the right or principled way to solve the problem. But it now seems to be working (unless I'm confused by something).

interstar
  • 26,048
  • 36
  • 112
  • 180
  • 1
    Yes, this is essentially correct: you'll always need to include cljx's output path in the cljsbuild source path if cljx will be emitting code that contains macros used from ClojureScript. – cemerick Dec 21 '14 at 13:13