wrong number of args when using forward declared macro
clojure
Solution
Macros are evaluated at compile-time which means the compiler/reader has to know which symbols represent macros and which don't. By simply using `declare` like you do you're not supplying that information which means that instead of replacing the macro call with its evaluated value you'll have a reference to the macro function in your code.
In other words: the moment the reader encounters `my-macro` the first time it does not know any better than just leave it there. Since any macro is just a function (with the `:macro` metadata set to `true`) this does not pose a problem once it is defined further below.
You can check this fact by calling the macro function the "correct" way, supplying `&form` and `&env` parameters that would usually be implicitly passed:
(declare my-macro)
(defn my-function
[x]
(my-macro :form :env x))
(defmacro my-macro
[x]
(vector &form &env x))
(my-function (+ 1 2)) ;; => [:form :env 3]
Note that the form `(+ 1 2)` is evaluated before being passed to the "macro" since we're dealing with a plain-old function here.
You can declare a symbol as a macro using the aforementioned `:macro` metadata but this will only result in an exception when it is first called since the actual call is before the var is bound to anything:
(declare ^:macro my-macro)
(defn my-function
[x]
(my-macro x))
;; => IllegalStateException: Attempting to call unbound fn: #'user/my-macro ...
TL;DR: Declaring a macro will not work since it is called the moment it is encountered by the reader/compiler, no matter how deeply nested inside a function it is.
Problem
I have a function my-plus-in-macro that contains a macro named my-macro. But my-macro is declared after my-plus-macro definition. I use declare to avoid unable-to-resolve symbol error. I type these codes in my repl. ``` (declare my-macro my-plus) (defn my-plus-in-macro [x y] (my-macro (my-plus x y))) (defmacro my-macro [my-fn] `~my-fn) (defn my-plus [x y] (+ x y)) ``` Then, I expect to get 3 if execute this ``` (my-plus-in-macro 1 2) ``` but instead I get, ``` ArityException Wrong number of args (1) passed to: user$my-macro clojure.lang.AFn.throwArity (AFn.java:437) ``` But, if I execute this my-plus-in-macro definition again in the repl ``` (defn my-plus-in-macro [x y] (my-macro (my-plus x y))) ``` then I execute this (my-plus-in-macro 1 2) Just what I expect, 3 What happens in my first execution of (my-plus-in-macro 1 2)? Somehow, when I define my-plus-in-macro for the first time, clojure sees my-macro symbol but it doesn't know yet that I intend to use it as a name for a macro. Although I have define my-macro as a symbol right after I define my-plus-in-macro, clojure still doesn't know that my-macro is a symbol for a macro. That's why I get ArityException. But, somehow, when I redefine my-plus-in-macro with the same code, Clojure now knows that my-macro is a macro and treats it as such and then my code works. Of course I don't get any exception if I put my-macro definition before my-plus-in-macro definition. But does that mean I can not use declare to reserve a symbol for a macro? EDIT based on answer from @xsc, these code works. I just have to call my-macro in my-plus-in-macro definition using "correct" way by supplying :form and :env ``` (declare my-macro my-plus) (defn my-plus-in-macro [x y] (my-macro :form :env (my-plus x y))) (defmacro my-macro [my-fn] `~my-fn) (defn my-plus [x y] (+ x y)) (my-plus-in-macro 1 2) 3 ``` EDIT-0 @xsc you are right, I can not use declare to forward-declare symbols for macros. I must put macro definition before any function that use it. so, this is the right code ``` (declare my-plus) (defmacro my-macro [my-fn] `~my-fn) (defn my-plus-in-macro [x y] (my-macro (my-plus x y))) (defn my-plus [x y] (+ x y)) (my-plus-in-macro 1 2) 3 ```