Спецификация Clojure: как проверить ту или иную карту

У меня есть этот код Clojure, чтобы определить мою схему для объектов ответа, которые могут быть

{:message {:text "Hello"} :delay 3000}

или же

{:action "typing_on" :duration 5000}

reply карта может иметь :message или же :action и соответственно дополнительные ключи :delay а также :duration,

Я пытаюсь выразить это так clojure.spec:

(s/def ::action #{"typing_on" "typing_off" "mark_seen"})
(s/def ::duration int?)
(s/def ::delay int?)
(s/def ::message map?)

(s/def ::message-reply (s/keys :req-un [::message]
                               :opt-un [::delay]))

(s/def ::action-reply (s/keys :req-un [::action]
                              :opt-un [::duration]))

(s/def ::reply (or ::action-reply ::message-reply))

Тем не менее, эти спецификации будут подтверждены с true только первая схема, которую они находят в or оговорка, в данном случае ::action-reply, Вместо этого я пытаюсь достичь ::action-reply или же ::message-reply действительные схемы для ::reply,

1 ответ

Решение

Я думаю, вы хотели использовать s/orне or (что на самом деле не имеет смысла в этом контексте)?

(s/def ::reply (s/or :action-reply  ::action-reply
                     :message-reply ::message-reply))

Возможно попробовать s/conform на одном из ваших значений, чтобы увидеть, как вы можете использовать соответствующее ('spec-destructured') значение:

(s/conform ::reply {:message {:text "Hello"} :delay 3000})
; => [:message-reply {:message {:text "Hello"}, :delay 3000}]
Другие вопросы по тегам