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.

Reply via email to