Thanks, this is going in the right direction.

The macro expansion looks correct, but the actual execution still
fails:

user=> (macroexpand '(def-fields fs tags))
(def fs (clojure.core/create-struct :name :age))


user=> (def-fields fs tags)
java.lang.Exception: Unable to resolve symbol: :name in this context
(NO_SOURCE_FILE:4)



Per


On May 20, 7:59 am, Michael Reid <kid.me...@gmail.com> wrote:
> On Wed, May 20, 2009 at 8:44 AM, pmf <phil.fr...@gmx.de> wrote:
>
> > On May 20, 4:47 am, Per <nondual...@gmail.com> wrote:
> >> ;; The macro
> >> (defmacro def-fields [name  tgs]
> >>   `(defstruct ~name ~@(map #(symbol (str ":" %)) tgs))
> >> )
>
> > If you replace the call to 'symbol' with a call to 'keyword', it works
> > (I think this is what you intended).
>
> I don't think its that simple. I still get the error if I change it to
> a call to 'keyword'. The problem I believe is that because def-fields
> is a macro, the arguments are not evaluated, so in the macro, tgs is
> bound to the symbol 'tags _not_ the value of tags as defined above the
> macro.
>
> I've encountered this myself several times, I'm not sure what the
> idiomatic way of handling this is but this change demonstrates what I
> am talking about:
>
> user> (def tags '("name" "age"))
> #'user/tags
> user> (defmacro def-fields [name tgs] `(defstruct ~name ~@(map
> #(symbol (str ":" %)) tgs)))
> #'user/def-fields
> user> (macroexpand-1 '(def-fields fs tags))
> ; Evaluation aborted.
> user> (defmacro def-fields [name tgs] `(defstruct ~name ~(.get
> (ns-resolve *ns* tgs))))
> #'user/def-fields
> user> (macroexpand-1 '(def-fields fs tags))
> (clojure.core/defstruct fs ("name" "age"))
>
> In my redefinition of the macro, I first resolve the symbol 'tags to
> get the Var, and then I get the value of the Var. This indeed returns
> the value of tags, but again, I'm not sure its the nicest solution.
> The downside here is that now you can't pass in a literal:
>
> user> (macroexpand-1 '(def-fields fs ("name" "age")))
>
> However, if you put in some logic into your macro, you can get both:
>
> (defmacro def-fields [name tgs]
>   `(defstruct ~name ~@(map #(symbol (str ":" %))
>                                           (if (symbol? tgs)
>                                              (.get (ns-resolve *ns* tgs))
>                                              tgs))))
>
> I think this yields what you want:
>
> user> (macroexpand-1 '(def-fields fs ("name" "age")))
> (clojure.core/defstruct fs :name :age)
> user> (macroexpand-1 '(def-fields fs tags))
> (clojure.core/defstruct fs :name :age)
>
> /mike.
--~--~---------~--~----~------------~-------~--~----~
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
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