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



根据规范指南

*正则表达式运算符:检查 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 s/cat?或者我如何检查类似[[:silent? false] [:verbose true]]的东西?

您可以使用

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]]

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

。因为正则表达式是平面序列的结构化规范。套用序列规范指南...

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

我怎样才能指定类似[[:silent? false] [:verbose true]]的东西?

要规范一系列对,每个对都是一个关键字,后跟一个布尔值:

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

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

=> (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.

最新更新