Spec {{instrument}} 不在协议方法上工作。无效的参数将被静默接受而没有错误。协议变量包含在 {{(instrument)}} 的返回值中。
重现步骤
`
(require
'[clojure.spec :as s]
'[clojure.spec.test :as test])
(defprotocol P
(method [this arg]))
(defrecord R []
P
(method [this arg]
(str "R.method called with " (pr-str arg))))
(s/fdef method
:args (s/cat :this any?
:arg number?))
(defn wrapped [this arg]
(method this arg))
(s/fdef wrapped
:args (s/cat :this any?
:arg number?))
(test/instrument)
(println (method (->R) "not a number"))
(println (wrapped (->R) "not a number"))
`
此代码输出结果
R.method 调用 "not a number" clojure.lang.ExceptionInfo: 调用 #'user/wrapped 未符合规范:在 [1] val: "not a number" 未通过:[:args :arg]谓词:number? ...
可能的解决方案
- 为 {{instrument}} 添加对协议方法的支持
- 记录 {{instrument}} 不适用于协议方法,不要从 {{(instrument)}} 返回协议方法变量,当协议方法变量包含在传递给 {{(instrument syms)}} 的符号中时抛出异常
另请参阅
CLJ-1941 描述了一个不同的案例,其中 {{instrument}} 不工作。这个问题是在http://dev.clojure.org/jira/browse/CLJ-1941?focusedCommentId=43084&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-43084 文本:评论中确定的。
解决方案
可以通过将协议方法包装在普通函数中并对函数进行规范来避免此问题。这已经是常见做法。