自定义定义的文档字符串

时间:2014-05-16 15:03:02

标签: clojure documentation

在我正在研究的项目中,我们经常为不同的目的定义自定义defsomething - 样式的宏以隐藏样板。一个例子是defhook,它有助于为事件定义一个钩子处理程序。这是它的简化版本(实际版本有更多参数,并在defmethod中做了一些非平凡的事情,但这与我的问题无关):

(defmulti handle-hook
  "This multimethod is called when an event was fired."
  (fn [event context] event))

(defmacro defhook
  "Define a hook for an event."
  [event docstring & more]
  `(let [body# (fn ~@more)]
     (defmethod handle-hook ~event [event# context#]
       (body# context#))))

(defhook "EntryDeleted"
  "Hook called on entry deletion."
  [context]
  (log-deletion (:EntryID context)))

我对此代码的主要问题是defmethod不支持docstring,因此我不能在REPL中使用"EntryDeleted"或自动生成文档。最后一个对于项目很重要:有defhookdefhandler作为外部API公开,目前我们必须单独(和手动)维护文档。

所以最简单的问题是“如何将docstring附加到defmethod”?

更深层的是“如何附加/生成自定义defsomething宏的文档?”

如果某些现有的文档生成工具支持此功能,那就太棒了!然而,MarginaliaCodoxAutodoc似乎都不支持此类内容。

1 个答案:

答案 0 :(得分:1)

  

如何附加/生成自定义defsomething宏的文档?

由于文档字符串附加到变量,因此您通常会将defsomething个宏扩展为更原始的def形式,例如defndef。然后,您只需安排将defsomething的文档字符串附加到基础var。

  

如何将docstring附加到defmethod

这是一个特例 - defmethod没有定义新的var;它在Java对象上调用Java方法。另一方面,defmulti确实创建了一个var。一种想法是使用调度值和相关描述扩展多功能的文档字符串。例如,

(defn append-hook-doc! [event docstring]
  (let [hook-doc (str event " - " docstring)]
    (alter-meta! #'handle-hook
                 (fn [m]
                   (update-in m [:doc] #(str % "\n\t" hook-doc))))))
...
(doc handle-hook)
-------------------------
user/handle-hook
  This multimethod is called when an event was fired.
      EntryDeleted - Hook called on entry deletion.

正如!所示,此表单有副作用:对调用此表单的定义表单进行多次评估将导致#'handle-hook的docstring中出现重复行。您可以通过在#'handle-hook中存储一些额外的元数据来避免这种情况,以用作是否已附加文档的标记。或者,您可以将文档字符串存储在其他地方,并在一些辅助步骤中将它们全部修补,例如通过延迟(defmulti handle-hook ...的扩展直到你拥有所有的文档字符串(尽管,这打破了文档字符串的多方法的开放扩展)。