如何解决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))
可以正常工作(按预期),但是有一种方法可以按照规范顺序的优先级来匹配地图条目?
其工作方式如下:
- 获取所有值的地图条目(即地图)
- 将地图条目分成两组。一个确认
::a
规范,另一个确认::b
规范。 - 两个子图应该整体上符合每个相关规范。例如,第一个分区应具有所有必需的键。
解决方法
您可以通过将地图不视为地图而是作为地图条目的集合来处理,然后验证地图条目。处理“必需”键部分必须通过添加附加谓词来完成。
(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?))
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。