2

我有这个 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

4

1 回答 1

6

我猜你的意思是使用s/or, not 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}]
于 2017-07-06T17:18:24.973 回答