将可选的docstring添加到def*宏

dea*_*ost 2 macros clojure

我想在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"}])
Run Code Online (Sandbox Code Playgroud)

我想要:

(defhtml include-css
  "My optional docstring here."
  [:link {:href href :rel "stylesheet"}])
Run Code Online (Sandbox Code Playgroud)

我认为应该有一些常见的习惯用法.

Kyl*_*ton 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)))))
Run Code Online (Sandbox Code Playgroud)

这应该产生你想要的宏扩展:

(defhtml include-css [href]
  [:link {:href href :rel "stylesheet"}])
Run Code Online (Sandbox Code Playgroud)

生产:

(defn include-css
    "HTML Generator include-css"
  [href]
  (html [:link {:href href, :rel "stylesheet"}]))
Run Code Online (Sandbox Code Playgroud)

而:

(defhtml include-css
  "Standard css includes fory my site"
  [href]
  [:link {:href href :rel "stylesheet"}])
Run Code Online (Sandbox Code Playgroud)

生产:

(defn include-css
    "Standard css includes fory my site"
  [href]
  (html [:link {:href href, :rel "stylesheet"}]))
Run Code Online (Sandbox Code Playgroud)