Вы можете задокументировать функцию defmethod
, используя символ , как показано ниже:
(ns tst.demo.core
(:use tupelo.core tupelo.test))
(defmulti ident
(fn [item] (type item)) )
; vvvvvv-function-name
(defmethod ident clojure.lang.Keyword ident-fn-kw [item]
"to my heart")
(defmethod ident java.lang.String ident-fn-str [item]
"like cheese")
(defmethod ident clojure.lang.Symbol ident-fn-sym [item]
"crash, bang"
;(throw (ex-info "surprise!" {:reason :dont-need-one}))
)
(dotest
(is= clojure.lang.Keyword (spyx (type :hello)))
(is= java.lang.String (spyx (type "hello")))
(is= clojure.lang.Symbol (spyx (type 'hello)))
(is= "to my heart" (ident :hello))
(is= "like cheese" (ident "hello"))
(is= "crash, bang" (ident 'hello))
)
с результатом:
----------------------------------
Clojure 1.10.1 Java 13-ea
----------------------------------
Testing tst.demo.core
(type :hello) => clojure.lang.Keyword
(type "hello") => java.lang.String
(type (quote hello)) => clojure.lang.Symbol
Ran 2 tests containing 6 assertions.
0 failures, 0 errors.
и если вы раскомментируете throw
, вы получите символ, указанный в любой трассировке стека исключений, например:
ERROR in (dotest-line-19) (core.clj:16)
expected: (clojure.core/= "crash, bang" (ident (quote hello)))
actual: clojure.lang.ExceptionInfo: surprise!
{:reason :dont-need-one}
at tst.demo.core$eval23035$ident_fn_sym__23036.doInvoke (core.clj:16)
clojure.lang.RestFn.invoke (RestFn.java:408)
clojure.lang.MultiFn.invoke (MultiFn.java:229)
tst.demo.core$fn__23039.invokeStatic (core.clj:26)
tst.demo.core/fn (core.clj:19)
Обратите внимание, что «имя функции» включено в трассировку стека как tst.demo.core$eval23035$ident_fn_sym__23036
.Как и для любой «анонимной» функции, она может быть очень полезна для отслеживания причины исключения.Например:
(dotest
(let [add2 (fn add2-fn [a b] (+ a b))]
(is= 5 (add2 2 3))))
Здесь мы используем add2-fn
, чтобы назвать функцию в качестве средства отладки в случае исключения.Мне нравится использовать суффикс -fn
, так как он помогает ускорить поиск исходного кода на grep
.
Обновление:
Вот информация из clojuredocs.org
;; Methods can be given a name. Very useful in stack traces.
(defmethod foo "a" name-of-method [params] "was a")
Таким образом, name-of-method
является символом, а не строкой документа.
PS Обратите внимание, что для пользователя тот факт, что функция реализована как мульти-метод (по сравнению с обычной функцией)с cond
или if
или чем-то еще), на самом деле это просто деталь реализации.Контракт самой функции (имя, аргументы, цель и т. Д.) Определяется в форме defmulti
, и именно к ней относится строка документации.