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

Reply via email to