I have a CLJC file that produces the following desired output in Clojure:
(ns myproj.macros-ns)
(defmacro inner-macro [s]
`['(my-ns/my-fn) :from ['~s :all]])
(defmacro outer-macro [y xs]
`(into ['~y '~'<-] (eval '~xs)))
(defmacro macro-context [other-macros]
(let [symbols (eval other-macros)
_ (println "Expanded in macro context" symbols)]
{:result `(list '~symbols '~'+ '~'further-rearrangement)}))
(macro-context (outer-macro ?sym-a (inner-macro ?sym-b)))
Expanded in macro context [?sym-a <- (my-ns/my-fn) :from [?sym-b :all]]
=> {:result ([?sym-a <- (my-ns/my-fn) :from [?sym-b :all]] + further-rearrangement)}
My question is: How can I get the same result in Clojurescript?
My CLJS file looks like this:
(ns myproj.app-ns
(:require-macros [myproj.macros-ns :refer [outer-macro
inner-macro
macro-context]]))
(enable-console-print!)
(macro-context (outer-macro ?sym-a (inner-macro ?sym-b)))
Error I'm getting is:
clojure.lang.ExceptionInfo: java.lang.RuntimeException: Unable to
resolve symbol: outer-macro in this context, compiling:
(/private/var/folders/2g/sfp74ftj6_q1vw51ytjbgvph0000gn/T/form-
init4244939051951953637.clj:13:3) at line 12
test/macros/cljs/myproj/app_ns.cljs
What am I ultimately trying to do and why?
I'm writing a framework that wraps https://github.com/cerner/clara-rules. Clara has its own macro, defrule
, that uses the following DSL syntax
(defrule my-rule
[?fact <- (my-ns/my-fn) :from [:all (= ?e (:e this))]
...
I have a macro that expands the following to the previous:
(macro-context my-rule
[?fact <- (my-ns/my-fn) :from [?e :all]]
...
The macro that does this is basically the macro-context
in the more general example above. When I am only parsing syntax like this, I don't call eval
or macroexpand
. I'm able to treat everything as a symbol, rewrite it to Clara's DSL, then pass it to defrule
.
Here's where I think that breaks down:
(macro-context
[(outer-macro ?fact (inner-macro ?e))]
...
Inside the macro-context
macro, outer-macro
and inner-macro
are unevaluated and at that point I need their expansion. By calling eval, I can get that in Clojure, but for some reason when compiling Clojurescript I receive "unable to resolve symbol outer-macro
in this context.
macroexpand
instead ofeval
. – ClojureMostlyf
andg
are both macros, then(macroexpand '(f (g x)))
is different from(eval '(f (g x)))
(or the usual thing, simply writing(f (g x))
): the first of those does not expandg
, while the last two do. – amalloy