2

私は比較的 clojure に慣れていないので、必要なキーの値を別のキーの検証に使用する方法を探しています。2 つの値を使用して別のマップを作成し、それを渡すことでそれを行うことができますが、もっと簡単な方法があることを望んでいました。ありがとう

(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
  ]))
4

1 に答える 1

1

これを行う方法は次の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の別の述語を -ing することです。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 %)))))

このアプローチは拡張可能であるため、述語にすべてのロジックを保持するのではなく、後でさらにs をmulti-spec定義できるため、このアプローチを好むかもしれません。defmethodcountryand

于 2018-05-05T10:44:32.647 に答える