April 3, 2023
By: Kevin

Clojure docstring

  1. ns
  2. defn, defmacro, defn-
  3. def
  4. defprotocol
  5. defmulti
  6. mount.core/defstate

最近在写一个Clojure代码统计工具的时候, 需要把docstring计算为注释的一部分, 做了个更深入的了解.

第一个问题就是, 哪些结构可以有docstring?

ns, def, defn, defprotocol, defmacro, defmulti都可以使用docstring.

defrecord, deftype, defmethod反而不能用, 是不是有点意外?

本质上的原因是docstring是var(clojure.lang.Var)这个类型的metadata.

如果定义的类型是直接的Java类型, 而不是var, 则不能使用docstring

分别举几个🌰

ns

命名空间(namespace)应该有自己的docstring.

(ns device-sensor.socket.tcp
  "TCP通讯, 可以扩展支持其他tcp协议.
   主要功能为tcp连接, tcp的包到具体协议帧的组装, 帧组装完整后的处理(放到对应的stream)

  对外提供服务的有如下函数:

  1. `parse-x-packages`: 处理xa package, 参数为xa协议的tcp client
  2. `parse-x-packages`: 处理x package, 参数为a协议的tcp client
  3. `parse-f-packages`:  处理 FSMD加速卡package, 参数为FSMD协议的tcp client"
  {:author "lizy", :last-update-date "2022-02-28"}
  (:require
   [taoensso.timbre :as timbre :refer [debug error log spy]]))

defn, defmacro, defn-

对于docstring来说写法是一样的.

(defn raw-client
  "以`host`和`port` 为参数, 返回一个defered aleph客户端"
  [host port]
  (tcp/client {:host host, :port port}))

如果是multi-arity(不同参数个数的重载)的情况, 只能有一个docstring

(defn my-func
  "这是 my-func 的文档字符串。支持以下重载:
  - (my-func x) 做了某些事情
  - (my-func x y) 做了另一些事情
  - (my-func x y z) 做了不同的事情"
  ([x] (...))
  ([x y] (...))
  ([x y z] (...)))

def

名字之后, 定义之前

(def a-bf "doc string for a-buf" (atom nil))

defprotocol

需要protocol的函数定义中写明docstring

(defprotocol MainTask
  "定义了主任务的所有操作接口, 需要实现以下函数"
  (immediate?       "如果立即执行返回true, 否则false"
    [this])
  (gen-sub-tasks    "生成子任务"
    [this order])
  (run-task!        "立即执行的任务直接执行,不走schedule机制"
    [this order])
  (schedule-task!   "用于执行主任务的调度, 关联定时器, 定时器触发给设备下发指令"
    [this order])
  (cancel-schedule! "取消任务"
    [this])
  (change-state     "任务状态修改"
    [this order]))

defmulti

docstring只能加在defmulti中, defmethod不行呀, 只能老老实实去写注释.

(defmulti msg-handler
  "根据不同的编码分别进行处理"
  :sub-cmd-result-func-code)

(defmethod msg-handler :func-code1
  ;; 只能在这里写注释了, 不能有docstring
...)
(defmethod msg-handler :func-code2
  ;; 只能在这里写注释了, 不能有docstring
...)

mount.core/defstate

mount.core中, defstate支持docstring.

(defstate schedulers
  "对应多个`operation`的多任务系统, 这个atom用于存储多个context的状态"
  :start (atom {})
  :stop (when (seq @schedulers)
          (debugf "调度器结束 %s" (str (keys @schedulers)))))
(clojure.repl/doc schedulers)

;; -------------------------
;; clj-scheduler.schedulers/schedulers
;;   对应多个`operation`的多任务系统, 这个atom用于存储多个context的状态
Tags: clojure