Clojure规格图

问题描述

具有以下两个规格:

(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. 两个子图应该整体上符合每个相关规范。例如,第一个分区应具有所有必需的键。

解决方法

您可以通过将地图不视为地图而是作为地图条目的集合来处理,然后验证地图条目。处理“必需”键部分必须通过添加附加谓词来完成。

(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?))

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...