地图的 clojure 规范及其值

Pet*_*ull 4 clojure clojure.spec

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

(s/def ::value ???)
(s/def ::red (s/keys :req [::value ...]))
(s/def ::blue (s/keys :req [::value ...]))
Run Code Online (Sandbox Code Playgroud)

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

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

Ale*_*ler 5

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

(s/def ::red (s/keys :req [:red/value ...]))
(s/def ::blue (s/keys :req [:blue/value ...]))
Run Code Online (Sandbox Code Playgroud)

您可以将这些规格与地图一起使用,例如:

(s/valid? ::red {:red/value "foo"})
(s/valid? ::blue {:blue/value 100})
Run Code Online (Sandbox Code Playgroud)

此外,如果您必须使用的话,还s/keys支持将命名规范链接到非限定属性名称的选项。:req-un

(s/def ::red (s/keys :req-un [:red/value ...]))
(s/def ::blue (s/keys :req-un [:blue/value ...]))
Run Code Online (Sandbox Code Playgroud)

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

(s/valid? ::red {:value "foo"})
(s/valid? ::blue {:value 100})
Run Code Online (Sandbox Code Playgroud)

  • 重新红色 - 是的。命名空间映射语法只是语法,因此 `#::red{:value "hi"}` 和 `{::red/value "hi"}` 是完全相同的数据。我的意思是,您可以使用其中任何一个,都没关系,这与数据是否符合规范完全正交。 (2认同)