"Invalid arity: 0" error in a macro

I pushed the brach to https://github.com/Respo/respo/commits/macro-%24

The macro I wrote:


(defmacro $ [tag props & children]
  `(let [props# ~props
         attrs# (respo.util.list/pick-attrs props#)
         styles# (if (contains? props# :style) (sort-by first (:style props#)) (list))
         event# (or (:on props#) (:event props#) {})
         child-map# (respo.util.list/arrange-children-old ~children)]
     {:name ~tag,
      :coord nil,
      :attrs attrs#,
      :style styles#,
      :event event#,
      :children child-map#}))

was used like:

       ($
        :div
        {:style widget/button, :on (if (:locked? state) {} {:click clear-done})}
        (<> "Clear2"))

But I got errors, I don’t understand this:



BTW, how do you debug macros?

I don’t see immediately what the problem, and I wasn’t sure how to get to a REPL inside your project. What’s your workflow like? Is there a way to get a piggieback/nrepl REPL?

In general to debug a macro you use macroexpand-1 (or possibly macroexpand)

Pass it a quoted form, and then see if the expansion is correct.

(macroexpand-1 
    '($
        :div
        {:style widget/button, :on (if (:locked? state) {} {:click clear-done})}
        (<> "Clear2")))

I got more details after trying:

foo.core$macros=> (defmacro $ [tag props & children]
             #_=>   `(let [props# ~props
             #_=>          attrs# (respo.util.list/pick-attrs props#)
             #_=>          styles# (if (contains? props# :style) (sort-by first (:style props#)) (list))
             #_=>          event# (or (:on props#) (:event props#) {})
             #_=>          child-map# (respo.util.list/arrange-children-old ~children)]
             #_=>      {:name ~tag,
             #_=>       :coord nil,
             #_=>       :attrs attrs#,
             #_=>       :style styles#,
             #_=>       :event event#,
             #_=>       :children child-map#}))
#'foo.core$macros/$
foo.core$macros=> (macroexpand '(foo.core/$ :div {} []))
(let*
 [props__41__auto__
  {}
  attrs__42__auto__
  (respo.util.list/pick-attrs props__41__auto__)
  styles__43__auto__
  (if
   (cljs.core/contains? props__41__auto__ :style)
   (cljs.core/sort-by cljs.core/first (:style props__41__auto__))
   (cljs.core/list))
  event__44__auto__
  (cljs.core/or (:on props__41__auto__) (:event props__41__auto__) {})
  child-map__45__auto__
  (respo.util.list/arrange-children-old ([]))]
 {:name :div,
  :coord nil,
  :attrs attrs__42__auto__,
  :style styles__43__auto__,
  :event event__44__auto__,
  :children child-map__45__auto__})

Finally located the problem, thheller pointed out that there is a (), which is a invocation:

  (respo.util.list/arrange-children-old ([]))]

So I have to convert it back to a list:

child-map# (respo.util.list/arrange-children-old (list ~@children))]