Clojure规范——用于映射及其值的说明书

4
我正在使用Clojure实现一份标准文档。总的来说,我很满意Clojure让我写出与标准不同部分相符的代码的方式。考虑未来,我正在尝试为此编写一个clojure.spec。在文档中,他们用命名字段定义了各种结构化数据元素。然而,不同结构中的字段具有相同的名称,例如'red'结构具有一个字符串'value'字段,但'blue'结构具有一个整数'value'字段。在编写规范时,我该如何处理这个问题呢?
(s/def ::value ???)
(s/def ::red (s/keys :req [::value ...]))
(s/def ::blue (s/keys :req [::value ...]))

据我了解,官方建议是:命名键应该在任何地方具有相同的语义。

那么我该如何处理呢?我可以将它们称为'red-value'和'blue-value',但这会使代码和标准之间的对应关系不够清晰。我能否将每个结构放置在其自己的命名空间中?

1个回答

5

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

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

谢谢。只是想确认我的理解 - ::red 中的红色与 :red/value 中的红色完全独立,对吗?此外,在这里有没有使用命名空间映射的方法,例如 #::red{ :value "hi" ... } - Peter Hull
2
红色 - 是的。命名空间映射语法只是语法,因此 #::red{:value "hi"}{::red/value "hi"} 是完全相同的数据。我的意思是,你可以使用任何一种方式,没有关系,这与数据是否符合规范完全无关。 - Alex Miller

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接