Clojure使用验证中另一个必需键的值

时间:2018-05-05 03:38:12

标签: clojure clojure.spec

我对clojure相对较新,我正在寻找一种方法来在另一个验证中使用一个必需键的值。我可以通过使用两个值创建另一个映射并传递它来实现它,但我希望有一种更简单的方法。感谢

(s/def ::country string?)
(s/def ::postal-code   
  ;sudo-code
  ;(if (= ::country "Canda")
  ;(re-matches #"^[A-Z0-9]{5}$") 
  ;(re-matches #"^[0-9]{5}$"))
)

(s/def ::address
  (s/keys :req-un [
    ::country
    ::postal-code
    ::street
    ::state
  ]))

1 个答案:

答案 0 :(得分:0)

以下是multi-spec

的方法
(defmulti country :country)
(defmethod country "Canada" [_]
  (s/spec #(re-matches #"^[A-Z0-9]{5}$" (:postal-code %))))
(defmethod country :default [_]
  (s/spec #(re-matches #"^[0-9]{5}$" (:postal-code %))))

(s/def ::country string?)
(s/def ::postal-code string?)
(s/def ::address
  (s/merge
    (s/keys :req-un [::country ::postal-code])
    (s/multi-spec country :country)))

(s/explain ::address {:country "USA" :postal-code "A2345"})
;; val: {:country "USA", :postal-code "A2345"} fails spec: :sandbox.so/address at: ["USA"] predicate: (re-matches #"^[0-9]{5}$" (:postal-code %))
(s/explain ::address {:country "Canada" :postal-code "A2345"})
;; Success!

另一个选项是and - 您的keys规范中的另一个谓词:

(s/def ::address
  (s/and
    (s/keys :req-un [::country ::postal-code])
    #(case (:country %)
       "Canada" (re-matches #"^[A-Z0-9]{5}$" (:postal-code %))
       (re-matches #"^[0-9]{5}$" (:postal-code %)))))

您可能更喜欢multi-spec方法,因为它可以进行扩展,即您可以稍后为defmethod定义更多country s,而不是保留and中的所有逻辑{1}}谓词。