2016-07-22 57 views
3

如果我定义了以下记录:Clojure的规范和记录构造

(defrecord Person [name id]) 

及以下:

(s/def ::name string?) 
(s/def ::id int?) 
(s/def ::person (s/keys :req-un [::name ::id])) 

我怎么能保证你不能创建不符合一个人到::人的规格?换句话说,下面应该抛出一个异常:

(->Person "Fred" "3") 

我想:

(s/fdef ->Person :ret ::person) 

但调用:

(->Person "Fred" "3") 

不会引发异常。

但是:

(s/conform ::person (->Person "Fred" "3")) 

不会产生预期:

:clojure.spec/invalid 

感谢

回答

5

fdef:滞留和:FN功能时clojure.spec.test/check测试仅检查,但你可以使用一个FDEF :args spec在检测时检查构造函数的输入。

(s/fdef ->Person 
    :args (s/cat :name ::name :id ::id) 
    :ret ::person) 

(require '[clojure.spec.test :as stest]) 
(stest/instrument `->Person) 

(->Person "Fred" "3") 

=> CompilerException clojure.lang.ExceptionInfo: Call to #'spec.examples.guide/->Person did not conform to spec: 
In: [1] val: "3" fails spec: :spec.examples.guide/id at: [:args :id] predicate: int? 
:clojure.spec/args ("Fred" "3") 
:clojure.spec/failure :instrument 
:clojure.spec.test/caller {:file "guide.clj", :line 709, :var-scope spec.examples.guide/eval3771} 

它不会是太难的宏defrecord和使用匹配规范构造的FDEF的组合。