根据规范指南
*
正则表达式运算符:检查 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/cat
的s/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
.