将 defn 符合 ::defn-args 规范可以正确保留对输入参数的类型提示,但是错误地丢失了对返回值的类型提示。
user=> (require '[clojure.spec.alpha :as s] '[clojure.core.specs.alpha :as ss])
nil
user=> (def c '(f ^double [^long x] 0.0))
#'user/c
user=> (binding [*print-meta* true] (prn c))
^{:line 10, :column 9} (f ^double [^long x] 0.0)
nil
user=> (binding [*print-meta* true] (prn (s/conform ::ss/defn-args c)))
{:name f, :bs [:arity-1 {:args {:args [[:sym ^long x]]}, :body [:body [0.0]]}]}
nil
*原因:* 符合正则表达式规格的却没有保留其在符合值上的元信息(集合规格则保留)
user=> (binding [*print-meta* true] (prn (s/conform (s/coll-of int?) ^{:hi :there} [1])))
^{:hi :there} [1]
user=> (binding [*print-meta* true] (prn (s/conform (s/* int?) ^{:hi :there} [1])))
[1]
出现此问题的特定规范是 :clojure.core.specs.alpha/arg-list,它是一个 s/*。