Perfect, thanks Stuart! That works great :) I put it in a convenience macro: ; Stuart Sierra (defmacro defn-with-doc "Like defn but accepts a procedurally generated string." [fun doc-str & body] `(let [f# (defn ~fun ~...@body)] (alter-meta! (var ~fun) assoc :doc ~doc-str) f#))
Got me thinking on a different line.... Laurent once remarked that it would be nice to attach argument descriptions as meta data: (defmacro defn-with-args "Like defn but takes non-literal string doc, and a map of arguments instead of a vector. args should be a map of argument names to descriptions." [fun doc-str args & body] `(let [f# (defn ~fun ~(vec (map symbol (keys args))) ~...@body)] (alter-meta! (var ~fun) assoc :doc ~(str doc-str \newline " " args)) (alter-meta! (var ~fun) assoc :argdescs ~(vec (vals args))) f#)) (let [m {:one 1, :two 2}] (defn-with-args foo1 "hi1" {"in1" "must be a string", "in2" (str "must be one of: " (keys m))} (println in1 (m in2)) (m in2))) ------------------------- test-extensions/foo1 ([in1 in2]) hi1 {"in1" "must be a string", "in2" (str "must be one of: " (keys m))} (println (:argdescs ^(var foo1))) [must be a string must be one of: (:one :two)] My code is almost but not quite, but you get the idea... I think this might be quite useful with a bit of improvement. I imagine Laurent is mostly interested in the arguments from an IDE perspective, but in general its nice to know precisely what arguments are expected. Also a few people have discussed the "by contract" style. Another possible extension would be to store preconditions: (def *debug* false) (defmacro check-preconditions "Ensure preconditions are met." [m] (if *debug* `(assert (apply = true (map #((val %) (key %)) ~m))))) (defmacro defn-by-contract "Like defn but takes non-literal string doc, and a map of arguments instead of a vector. args should be a map of strings to preconditions." [fun doc-str args & body] `(let [f# (defn ~fun ~(vec (map symbol (keys args))) (check-preconditions args) ~...@body)] (alter-meta! (var ~fun) assoc :doc ~(str doc-str \newline " " args)) (alter-meta! (var ~fun) assoc :argdescs ~(vec (vals args))) f#)) Actually preconditions should be handled completely separately perhaps as another metadata :argpreds, this code is just to illustrate a possibility. If anyone is interested in playing with this, feel free to use: http://github.com/timothypratley/strive/blob/baf83e2bb26662f5f5049d165dec31e47b91e171/clj/timothypratley/extensions.clj http://github.com/timothypratley/strive/blob/baf83e2bb26662f5f5049d165dec31e47b91e171/clj/timothypratley/test-extensions.clj Regards, Tim. --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---