Clojure规范映射

Clojure规范映射,clojure,clojure.spec,Clojure,Clojure.spec,具有以下两种规格: (s/def::x关键字?) (s/def::y关键字?) (s/def::z关键字?) (s/def::a) (s/keys:req un[::x) ::y] :opt un[::z])) (s/def::b) (字符串的s/map?字符串?) 如何将::a和::b合并到::m中,以使以下数据有效: (s/valid?::m) {:x:foo :y:bar :z:any}) (s/有效?::m {:x:foo :y:bar}) (s/有效?::m {:x:foo :y:b

具有以下两种规格:

(s/def::x关键字?)
(s/def::y关键字?)
(s/def::z关键字?)
(s/def::a)
(s/keys:req un[::x)
::y]
:opt un[::z]))
(s/def::b)
(字符串的s/map?字符串?)
如何将
::a
::b
合并到
::m
中,以使以下数据有效:

(s/valid?::m)
{:x:foo
:y:bar
:z:any})
(s/有效?::m
{:x:foo
:y:bar})
(s/有效?::m
{:x:foo
:y:bar
:z:baz})
(s/有效?::m
{:x:foo
:y:bar
:z“baz”})
(s/有效?::m
{:x:foo
:y:bar
:t“tic”})
此外,如何将
::a
::b
合并到
::m
中,以使以下数据无效:

(s/valid?::m)
{“r”“foo”
“t”“bar”})
(s/有效?::m
{:x:foo
“r”“bar”})
(s/有效?::m
{:x:foo
:y:bar
:r:any})
以下两项均不适用:


(s/def::m(s/merge::a::b))
(s/def::m(s/or:a::a:b::b))
工作正常(如预期),但是否有方法按照规范顺序匹配映射条目

其工作方式如下:

  • 获取值的所有映射项(这是一个映射)
  • 将地图条目分为两组。一个确认
    ::a
    规范,另一个符合
    ::b
    规范
  • 两个子贴图应整体符合每个相关规范。例如,第一个分区应该具有所有必需的密钥

  • 您可以通过不将映射视为映射,而是将其视为映射项的集合,然后验证映射项来实现这一点。处理“必需”键部分必须通过s/和'ing附加谓词来完成

    (s/def ::x keyword?)
    (s/def ::y keyword?)
    (s/def ::z keyword?)
    
    (s/def ::entry (s/or :x (s/tuple #{::x} ::x)
                         :y (s/tuple #{::y} ::y)
                         :z (s/tuple #{::z} ::z)
                         :str (s/tuple string? string?)))
    
    (defn req-keys? [m] (and (contains? m :x) (contains? m :y)))
    
    (s/def ::m (s/and map? (s/coll-of ::entry :into {}) req-keys?))
    

    为什么
    {“r”“foo”“t”“bar}
    无效?它符合
    ::b
    规范?它无效,因为它只符合
    ::b
    规范。我想定义一个既符合
    ::a
    又符合
    ::b
    的规范。例如
    ::a
    a需要
    :x
    :y
    ,并且当出现
    :z
    时,它必须是
    关键字。另外,
    ::m
    允许映射中的任意键,只要它们是字符串,并且它们的值也是字符串。这听起来和我不一样,因为::b中的“所有键都必须是字符串”违反了::a中的关键字。我还认为being
    :t“tic”
    是有效的。所以它要么是“:x,:y,也许是:z”,要么是任何带有字符串键和值的东西。@cfrick非常感谢您的评论。如果你是说,我没有清楚正确地阐述我的问题,你是绝对正确的。老实说,我不知道如何表达清楚。我希望我列举的例子能帮助我理解自己的需要。如果你能把我的问题改清楚一点,我将不胜感激。