Как документировать функцию defmethod? - PullRequest
1 голос
/ 26 сентября 2019

Как описано в defmethod doc , им может быть присвоено имя.Что очень полезно при трассировке стека.

(defmethod foo "a" name-of-method [params] "was a")

При замене name-of-method на строку.Я получаю следующую ошибку:

:cause "Call to clojure.core/fn did not conform to spec."                          
 :data #:clojure.spec.alpha{:problems ({:path [:fn-tail :arity-1 :params], :pred clo
jure.core/vector?, :val "A documentation", :via [:clojure.core.specs.alpha/params+bo
dy :clojure.core.specs.alpha/param-list :clojure.core.specs.alpha/param-list], :in [
0]} {:path [:fn-tail :arity-n], :pred (clojure.core/fn [%] (clojure.core/or (clojure
.core/nil? %) (clojure.core/sequential? %))), :val "A documentation", :via [:clojure
.core.specs.alpha/params+body :clojure.core.specs.alpha/params+body], :in [0]}), :sp
ec #object[clojure.spec.alpha$regex_spec_impl$reify__2509 0x24de08c1 "clojure.spec.a
lpha$regex_spec_impl$reify__2509@24de08c1"]

Итак, как лучше документировать дефметод?

1 Ответ

0 голосов
/ 26 сентября 2019

Вы можете задокументировать функцию 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, и именно к ней относится строка документации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...