【问题标题】:clojure specs for maps and their values地图及其值的 clojure 规范
【发布时间】:2017-03-27 23:04:29
【问题描述】:

我正在使用 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 ...]))

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

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

【问题讨论】:

    标签: clojure clojure.spec


    【解决方案1】:

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

    (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" ... }
    • 重新红色 - 是的。命名空间映射语法只是语法,所以#::red{:value "hi"}{::red/value "hi"} 是完全相同的数据。我的意思是,你可以使用其中任何一个,没关系,这与数据是否符合规范完全正交。
    猜你喜欢
    • 2020-01-08
    • 1970-01-01
    • 1970-01-01
    • 2014-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-21
    • 1970-01-01
    相关资源
    最近更新 更多