2017-07-06 28 views
1

我有这样的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的有效模式。

回答

5

我想你的意思是使用s/or而不是or(这在这种情况下没有意义)?

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

也许尝试按自己的价值观之一s/conform看你如何使用符合(“技术规范的解构”)值:

(s/conform ::reply {:message {:text "Hello"} :delay 3000}) 
; => [:message-reply {:message {:text "Hello"}, :delay 3000}] 
+0

我仍然不清楚为什么我需要在S按键/或条款,但这似乎正确地描述了我想要的。 – feychou

+4

@feychou“s/or”子句中的键允许您查看数据符合时采用哪个分支,或发生错误 – Josh

相关问题