Закрытие с использованием значения из другого обязательного ключа в проверке - PullRequest
0 голосов
/ 05 мая 2018

Я относительно новичок в 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 голосов
/ 05 мая 2018

Вот способ сделать это с 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 s для country позже, в отличие от сохранения всей логики в предикате and.

...