Internally macros are represented as a function with two additional arguments and a metadata tag. So:
(defmacro foo [x] x) Is equivalent to: (defn ^:macro foo [&form &env x] x) My guess is that you're hitting an edge case of the compiler. I don't think it's possible to use macros with a declare step, because the compiler needs to know what the macro is when it compiles the function. What I think is happening is that Clojure is assuming "myfn2" is a function when you declare it, and then when you later turn it into a macro, it's already been compiled into a function call. This is why you get the argument error, because when called as a function, the macro has two additional arguments that are usually implicit. - James On 9 November 2014 11:19, Angel Java Lopez <[email protected]> wrote: > Hi! > > I'm understand macros from other Lisp, and I implemented some simple Lisp > interpreters (not compilers) in Java and C#. > > But I still don't understand some Clojure decisions, like indicating > something is a macro in the metadata of a var. I guess those decisions are > related to COMPILING phase. > > Today, I found an unexpected error. In a clear REPL: > > user=> (declare myfn2) > #'user/myfn2 > user=> (defn myfn1 [x y] (myfn2 x y)) > #'user/myfn1 > user=> (defn myfn2 [x y] (+ x y)) > #'user/myfn2 > user=> (myfn1 1 2) > 3 > > This is OK. > > But again, in a new/clear REPL: > > user=> (declare myfn2) > #'user/myfn2 > user=> (defn myfn1 [x y] (myfn2 x y)) > #'user/myfn1 > user=> (defmacro myfn2 [x y] (cons 'list (cons x (cons y nil)))) > #'user/myfn2 > user=> (myfn1 1 2) > ArityException Wrong number of args (2) passed to: user/myfn2 > clojure.lang.AFn. > throwArity (AFn.java:429) > > Why? I expected something like: > - Invoke the macro > - Or invalid call to macro > > but why "wrong number of args"? > > In the same REPL, I continue with: > > user=> (defn myfn1 [x y] (myfn2 x y)) > #'user/myfn1 > user=> (myfn1 1 2) > (1 2) > > So, I redeclare myfn1, using myfn2 that now it is known as a macro, I > invoked myfn1 and myfn2 was invoked. OK. > > But now, if I redeclare myfn2 to a normal function: > > user=> (defn myfn2 [x y] (+ 1 2)) > #'user/myfn2 > user=> (myfn1 1 2) > (1 2) > user=> (myfn2 1 2) > 3 > > THE invocation to myfn1 is using the OLD myfn2 definition. My guess: > > - myfn1 was compiled, and at the time of compilation, myfn2 was a macro, > with some implementation > > The questions are: > > Am I right? It is a compiler related issue when using macros? > How myfn1 knows the PAST implementation of myfn2? It is the myfn2 initial > implementation EXPANDED at myfn1 compile time? What happens if myfn2 has > other macros inside? > > In other implementations, I expected myfn1 lookup for myfn2 value EACH > TIME myfn2 is used at head of list, independently of being myfn2 a macro or > not. For example, in a clear REPL > > user=> (defn myfn2 [x y] (+ x y)) > #'user/myfn2 > user=> (defn myfn1 [x y] (myfn2 x y)) > #'user/myfn1 > user=> (myfn1 1 2) > 3 > > It's OK. Then, I redefined myfn2: > > user=> (defn myfn2 [x y] (+ x y 1)) > #'user/myfn2 > user=> (myfn1 1 2) > 4 > > and THE NEW myfn2 is indirectly invoked. > > TIA > > Angel "Java" Lopez > @ajlopez > > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to [email protected] > Note that posts from new members are moderated - please be patient with > your first post. > To unsubscribe from this group, send email to > [email protected] > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en > --- > You received this message because you are subscribed to the Google Groups > "Clojure" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to [email protected] Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
