2016-07-22 6 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 specに?言い換えれば、以下は例外をスローする必要があります

(->Person "Fred" "3") 

私が試した:

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

が、呼び出し:

(->Person "Fred" "3") 

は、例外は発生しません。しかし

:clojure.spec/invalid 

おかげ

答えて

5

fdefを::RETと:FN仕様はclojure.spec.test/checkテスト時にチェックされていますが、FDEFを使用することができ

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

は予想し得ません:インストゥルメント時のコンストラクタ関数への入力をチェックする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の組み合わせをマクロ化することはあまり難しくありません。