* clojure.spec中的正则表达式运算符

时间:2019-04-08 06:11:12

标签: clojure clojure.spec

根据Spec Guide

*正则表达式运算符:检查0个或多个谓词/模式,如下所示:

(s/def ::seq-of-keywords (s/* keyword?))

;; opts are alternating keywords and booleans
(s/def ::opts (s/* (s/cat :opt keyword? :val boolean?)))
(s/conform ::opts [:silent? false :verbose true])
;;=> [{:opt :silent?, :val false} {:opt :verbose, :val true}]

但是据我了解,s/cat检查一个序列。

所以为什么(s/* (s/cat))不是要检查每个序列都符合(s/cat)的序列。

类似这样的东西:

(s/conform ::opts [[:silent? false] [:verbose true]])

为什么它的行为像s/* flatten ed s/cat?或如何检查类似[[:silent? false] [:verbose true]]的东西?

2 个答案:

答案 0 :(得分:1)

您可以使用coll-of来做到这一点:

(s/conform (s/coll-of ::opts) [[:silent? false] [:verbose true]])
=> [[{:opt :silent?, :val false}] [{:opt :verbose, :val true}]]

有时有助于生成示例数据:

(gen/generate (s/gen ::opts))
=> (:aqfR6b*C/.  false  :?.03/Vu7?  false  :Y17UL0/McsI5h  true)

[[:silent? false] [:verbose true]]的模式不匹配

但这可能应该更接近您要寻找的东西:

(gen/generate (s/gen (s/coll-of (s/tuple keyword? boolean?))))
=> [[:X_o.u?7i/o.dIgTy false]  [:L?*/_WY._:z true]  [:X26:-j/l2q!u-7I false]]

答案 1 :(得分:0)

  

为什么... s/*变平s/cat

...,因为正则表达式是 flat 序列的结构化规范。释义the Spec Guide to Sequences ...

  • 将正则表达式组合在一起时,它们描述的是单个序列。
  • 要指定嵌套序列,请将其包装在对s/spec的显式调用中。
  

如何指定类似[[:silent? false] [:verbose true]]的东西?

要指定成对的序列,每个对都是一个关键字,后跟一个布尔值:

(s/def ::opts (s/* (s/spec (s/cat :opt keyword? :val boolean?))))

请注意,s/spec包装了s/cat。现在,例如...

=> (s/conform ::opts [[:silent? false] [:verbose true]])
[{:opt :silent?, :val false} {:opt :verbose, :val true}]

您当然可以像akond一样使用

  • s/tuple而不是s/cat
  • s/coll-of而非s/*

,无需插入s/spec