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 -~----------~----~----~----~------~----~------~--~---