我想在我的def*
宏中添加可选的文档字符串。例如:
(defmacro defhtml
"Macro to avoid backtick unquote[splicing] in html vectors.
TODO: Add optional docstring."
[name args & body]
`(defn ~name ~args (html ~@body)))
;; Working defhtml
(defhtml include-css [href]
[:link {:href href :rel "stylesheet"}])
我想:
(defhtml include-css
"My optional docstring here."
[:link {:href href :rel "stylesheet"}])
我认为应该有一些常见的习惯用法。
答案 0 :(得分:5)
您需要决定宏的第二个参数是否是文档字符串(您可以测试它是否为字符串)。 Clojure宏是Clojure,因此您可以对传递给您想要的宏的表单执行任何逻辑或操作。如果不完全符合您的要求,这应该接近:
(defmacro defhtml [name & args]
(cond
;; doc-string?
(string? (first args))
(let [[doc-string args-list & body] args]
`(defn ~name ~doc-string ~args-list (html ~@body)))
:no-doc-string
(let [[args-list & body] args]
`(defn ~name ~(format "HTML Generator %s" name) ~args-list (html ~@body)))))
这应该产生你之后的宏观扩展:
(defhtml include-css [href]
[:link {:href href :rel "stylesheet"}])
产生
(defn include-css
"HTML Generator include-css"
[href]
(html [:link {:href href, :rel "stylesheet"}]))
,同时:
(defhtml include-css
"Standard css includes fory my site"
[href]
[:link {:href href :rel "stylesheet"}])
产生
(defn include-css
"Standard css includes fory my site"
[href]
(html [:link {:href href, :rel "stylesheet"}]))
答案 1 :(得分:2)
defn
和defmacro
已经支持可选文档字符串,因此,如果您的def*
宏扩展为对其中一个的调用,则可能不需要包含您自己的代码中的任何string?
检查。这是defhtml
的情况,可以这样实现:
;; also adding an optional attribute map parameter, because why not?
(defmacro defhtml [name doc? attr-map? params & body]
`(defn ~name ~doc? ~attr-map? ~params (html ~@body)))
;; equivalent, perhaps prettier:
(defmacro defhtml [name doc? attr-map? params & body]
`(defn ~@[name doc? attr-map? params] (html ~@body)))