Something is going on that I don't understand, in the interplay between metadata, def'ing vars, and macros. I find myself writing a lot of (defn myfn "doc" [x y z] (foo (bar (baz x y z)))), so I figured I'd write a defcomp macro that I could call like (defcomp myfn "doc" [x y z] foo bar baz), to make it clear what's going on (a composition), without having to write each arg twice, and still get IDE support for arglists and doc.
My first attempt was (defmacro defcomp [name doc args & fs] (let [fmeta {:doc doc :arglists (list args)} sym (with-meta name fmeta)] `(def ~sym (comp ~@fs)))) since my understanding was that metadata on the symbol is transfered to the var in a def (as in (def ^:private foo 1)). However, my simple testcase of (defcomp iterations "iterate some stuff" [f start] rest iterate) fails. It macroexpands to (def iterations (clojure.core/comp trim-seq rest iterate)), and if I examine the metadata of the symbol in the expansion I see what I expect: user=> (-> '(defcomp ...) macroexpand second meta :arglists) ([f start]) But if I don't quote the defcomp, letting the compiler actually run it, I get "Unable to resolve symbol: f in this context". Why is this being eval'ed in the expansion context, when it's a quoted symbol in the metadata of the symbol? I was able to construct a working version: (defmacro defcomp [name doc args & fs] (let [fnmeta {:doc doc :arglists `'(~args)}] `(def ~(with-meta name fnmeta) (comp ~@fs)))) But honestly that leaves me even more in the dark. I don't understand how it works - the meta is being quoted too many times. Can anyone explain to me what I'm missing? -- 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