地图及其值的clojure规范

时间:2016-11-14 10:28:40

标签: clojure clojure.spec

我正在使用Clojure来实现(书面)标准文档。总的来说,我很高兴Clojure允许我编写符合标准不同部分的代码。着眼未来,我正在尝试为它写一个clojure.spec。在文档中,他们使用命名字段定义各种结构化数据元素。但是,不同结构中的字段具有相同的名称,例如“红色”结构具有“值”字段,该字段是字符串,但“蓝色”结构具有“值”字段,该字段是整数。在编写规范时我该如何处理?

(s/def ::value ???)
(s/def ::red (s/keys :req [::value ...]))
(s/def ::blue (s/keys :req [::value ...]))

据我所知,official advice是命名密钥应该在任何地方都具有相同的语义。

我该如何处理?我可以将它们称为“红色值”和“蓝色值”,但这使得代码和标准之间的对应关系不那么清晰。我可以将每个结构放在自己的命名空间中吗?

1 个答案:

答案 0 :(得分:4)

您的示例使用当前命名空间来表示所有规范名称,但您应该利用命名空间来消除名称的歧义。

(s/def ::red (s/keys :req [:red/value ...]))
(s/def ::blue (s/keys :req [:blue/value ...]))

您可以将这些规格用于以下地图:

(s/valid? ::red {:red/value "foo"})
(s/valid? ::blue {:blue/value 100})

此外,s/keys支持:req-un选项,可将命名规范链接到不合格的属性名称,如果这是您必须使用的内容。

(s/def ::red (s/keys :req-un [:red/value ...]))
(s/def ::blue (s/keys :req-un [:blue/value ...]))

您可以使用以下值进行验证:

(s/valid? ::red {:value "foo"})
(s/valid? ::blue {:value 100})