I don't know why it doesn't work. However, changing defgreeter to the
following seems work.

(defmacro defgreeter [greeter-name]
  (let [greeter (make-greeter)]
    `(def ~greeter-name ~greeter)))

Might be a clue. :)

Jonathan


On Sun, Dec 16, 2012 at 6:49 PM, juan.facorro <juan.faco...@gmail.com>wrote:

> I think it has to do with the closure in the *fn *used when generating
> the form in the macro.
>
> If you change this function:
>
> *(defn make-greeter []*
> *  (let [message "hello"]*
> *    (fn [user-name]*
> *      (str message ", " user-name))))*
>
> To this one:
>
> *(defn make-greeter []
> *
> *  (fn [user-name]*
> *    (let [message "**hello**"]*
> *      (str message ", " user-name))))*
>
> There's no closure on the *message* local var, so you don't get any
> errors when the form the macro produces is compiled.
>
> *constantly** *also creates a closure on its argument:
>
> *(defn constantly*
> *  "Returns a function that takes any number of arguments and returns x."*
> *  {:added "1.0"*
> *   :static true}*
> *  [x] (fn [& args] x))*
>
> So the source of the problem seems to be the same.
>
> Although I'm not completely sure why this doesn't work, I think it kind of
> makes sense since the *fn* returned by *make-greeter* is actually
> produced in the *defmacro* body and not in the form generated, somehow
> the closure is lost and the error is generated.
>
> Someone with a better understanding of macros please jump in.
>
> Juan
>
> On Sunday, December 16, 2012 11:24:35 AM UTC-3, jarppe wrote:
>>
>> Hi,
>>
>> I have this macro (complete file 
>> https://www.refheap.com/paste/**7633<https://www.refheap.com/paste/7633>
>> ):
>>
>> *(*defmacro defgreeter [greeter-name]
>>
>>   *(*let [greeter *(*make-greeter*)*]
>>
>>     `*(*do
>>
>>        *(*defn ~greeter-name [user-name#]
>>
>>          *(*~greeter user-name#*)**)**)**)**)*
>>
>>
>> It works as expected when make-greeter is defined like this:
>>
>> *(*defn make-greeter []
>>
>>   *(*fn [user-name]
>>
>>     *(*str "Hello, " user-name*)**)**)*
>>
>>
>> I can use it like this:
>>
>> *(*defgreeter hello*)*
>>
>> *(*hello "jarppe"*)*
>>
>> How ever, if I change make-greeter to this I get IllegalArgumentException:
>>
>> *(*defn make-greeter []
>>
>>   *(*let [message "hello"]
>>
>>     *(*fn [user-name]
>>
>>       *(*str message ", " user-name*)**)**)**)*
>>
>>
>> Interestingly, this does not work either:
>>
>> *(*defn make-greeter []
>>
>>   *(*constantly "what erver"*)**)*
>>
>> What am I missing?
>>
>> --
>> -jarppe
>>
>>  --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> 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 post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to