3

Consider this pseudo code:

(defrc name
  "string"
    [a :A]
    [:div a])

Where defrc would be a macro, that would expand to the following

(let [a (rum/react (atom :A))]
  (rum/defc name < rum/reactive []
    [:div a]))

Where rum/defc is itself a macro. I came up with the code below:

(defmacro defrc
          [name subj bindings & body]
          (let [map-bindings# (apply array-map bindings)
                keys# (keys map-bindings#)
                vals# (vals map-bindings#)
                atomised-vals# (atom-map vals#)]
               `(let ~(vec (interleave keys# (map (fn [v] (list 'rum/react v)) (vals atomised-vals#))))
                     (rum/defc ~name < rum/reactive [] ~@body))))

Which almost works:

(macroexpand-all '(defrc aname
       #_=>   "string"
       #_=>   [a :A]
       #_=>   [:div a]))
(let* [a (rum/react #object[clojure.lang.Atom 0x727ed2e6 {:status :ready, :val nil}])] (rum/defc aname clojure.core/< rum/reactive [] [:div a]))

However when used it results in a syntax error:

ERROR: Syntax error at (clojure.core/< rum.core/reactive [] [:div a])

Is this because the inner macro is not being expanded?

2
  • Ah, seems this comes from rum itself, in parse-defc, investigating.. Commented Dec 19, 2015 at 18:00
  • 1
    sorry, having a hard time picturing the expected behaviour, can you provide a few examples? Commented Dec 19, 2015 at 23:33

1 Answer 1

1

Turns out the macro was working correctly but the problem occurred because < was inside the syntax quote it got expanded to clojure.core/<, and Rum simply looks for a quoted <, relevant snippet from Rum's source:

...(cond
        (and (empty? res) (symbol? x))
          (recur {:name x} next nil)
        (fn-body? xs)        (assoc res :bodies (list xs))
        (every? fn-body? xs) (assoc res :bodies xs)
        (string? x)          (recur (assoc res :doc x) next nil)
        (= '< x)             (recur res next :mixins)
        (= mode :mixins)
          (recur (update-in res [:mixins] (fnil conj []) x) next :mixins)
        :else
          (throw (IllegalArgumentException. (str "Syntax error at " xs))))...
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.