【问题标题】:Clojure spec mapsClojure 规范映射
【发布时间】:2020-10-05 08:12:41
【问题描述】:

有以下两个规格:

(s/def ::x keyword?)
(s/def ::y keyword?)
(s/def ::z keyword?)

(s/def ::a
  (s/keys :req-un [::x
                   ::y]
          :opt-un [::z]))

(s/def ::b
  (s/map-of string? string?))

如何将::a::b 组合成::m 使以下数据有效:

(s/valid? ::m
           {:x :foo
            :y :bar
            :z :any})

(s/valid? ::m
          {:x :foo
           :y :bar})

(s/valid? ::m
          {:x :foo
           :y :bar
           :z :baz})

(s/valid? ::m
          {:x :foo
           :y :bar
           :z "baz"})

(s/valid? ::m
          {:x :foo
           :y :bar
           :t "tic"})

另外,我如何将::a::b 组合成::m 所以以下数据无效:

(s/valid? ::m
          {"r" "foo"
           "t" "bar"})

(s/valid? ::m
          {:x :foo
           "r" "bar"})

(s/valid? ::m
           {:x :foo
            :y :bar
            :r :any})

两者都不是:


(s/def ::m (s/merge ::a ::b))

(s/def ::m (s/or :a ::a :b ::b))

工作(如预期),但有没有办法按照规范顺序的优先级匹配地图条目?

它应该工作的方式如下:

  1. 取值的所有映射条目(即映射)
  2. 将映射条目分成两组。一个确认::a 规范,另一个符合::b 规范。
  3. 这两个子图应符合每个相关规范作为一个整体。例如,第一个分区应该有所有必需的键。

【问题讨论】:

  • 为什么{"r" "foo" "t" "bar"} 无效?是否符合::b 规范?
  • 它无效,因为它仅符合 ::b 规范。我想定义一个符合::a::b 的规范。例如 ::a a 需要 :x:y 并且可选地,当 :z 存在时,它必须是 keyword。此外,::m 允许映射中的任意键,只要它们是字符串并且它们的值也是字符串。
  • 这听起来不像 AND,因为 ::b 中的“所有键都必须是字符串”违反了 ::a 中的关键字。我还认为:t "tic" 是有效的。所以它要么是“:x,:y,也许是:z”或任何带有字符串键和值的东西。
  • @cfrick 非常感谢您的 cmets。如果你说,我没有清楚正确地阐述我的问题,你是绝对正确的。老实说,我不知道如何表达清楚。我希望我所包含的示例确实有助于理解我的需求。如果您能将我的问题重新表述得更清楚,我将不胜感激。

标签: clojure clojure.spec


【解决方案1】:

您可以通过将映射不作为映射而是作为映射条目的集合来执行此操作,然后验证映射条目。处理“必需”键部分必须通过 s/and'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?))

【讨论】:

    猜你喜欢
    • 2016-11-20
    • 2017-06-13
    • 2017-09-13
    • 1970-01-01
    • 2019-11-29
    • 2011-02-10
    • 2015-08-02
    • 2012-06-12
    • 1970-01-01
    相关资源
    最近更新 更多