自定义定义的文档字符串

fiz*_*ruk 5 documentation clojure

在我正在处理的项目中,我们经常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)))
Run Code Online (Sandbox Code Playgroud)

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

所以最简单的问题是“如何将文档字符串附加到defmethod”?.

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

如果一些现有的文档生成工具支持此功能,那就太好了!然而,MarginaliaCodoxAutodoc似乎都不支持这样的东西。

Ian*_*ebo 1

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

由于文档字符串附加到变量上,因此通常会将defsomething宏扩展为更原始的def形式,例如defn, def。然后,您只需将 的defsomething文档字符串附加到底层变量即可。

如何将文档字符串附加到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.
Run Code Online (Sandbox Code Playgroud)

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