clojure - clojure.spec 中的禁止键

标签 clojure clojure.spec

我正在关注clojure.spec guide 。我知道使用 clojure.spec/keys 时可以声明必需和可选属性。

我不明白可选是什么意思。对我来说 :opt 没有做任何事情。

(s/valid? (s/keys :req [:my/a]) {:my/a 1 :my/b 2}) ;=> true

(s/valid? (s/keys :req [:my/a] :opt []) {:my/a 1 :my/b 2}) ;=> true

指南 promise 向我解释这一点,“我们稍后会看到可选属性在哪里有用”,但我找不到解释。我可以声明禁止使用的 key 吗?或者以某种方式声明有效键集等于 :req 和 :opt 中的键?

最佳答案

这是一个非常好的问题,clojure.spec API给出(理所当然的、简短的、令人不满意的)答案:

The :opt keys serve as documentation and may be used by the generator.

我认为如果 map 包含额外的(我认为这就是“禁止”的意思) key ,您就不能使用此方法使 map 无效。但是,您可以使用此规范来确保::bad-key 不存在:

(s/def ::m (s/and (s/keys :req [::a]) #(not (contains? % ::bad-key))))
(s/valid? ::m {::a "required!"})                        ; => true
(s/valid? ::m {::a "required!" ::b "optional!"})        ; => true
(s/valid? ::m {::a "required!" ::bad-key "no good!"})   ; => false

您可以使用此规范将键的数量限制为您想要的数量:

(s/def ::r (s/and (s/keys :req [::reqd1 ::reqd2]) #(= (count %) 2)))
(s/valid? ::r {::reqd1 "abc" ::reqd2 "xyz"})              ; => true
(s/valid? ::r {::reqd1 "abc" ::reqd2 "xyz" ::extra 123})  ; => false

不过,在我看来,处理此问题的最佳方法是简单地忽略存在您不关心的关键存在。

希望随着规范的成熟,这些好东西将会被添加。或者,也许它们已经在那里了(它正在迅速变化)而我只是不知道。这是 clojure 中的一个非常新的概念,因此我们大多数人都有很多东西需要学习。

更新 - 2016 年 12 月 我只是想在写这篇文章六个月后重温一下。看起来我最初关于忽略您不关心的键的评论是首选方法。事实上,在我两周前参加的 clojure/conj session 上,Rich 的主题演讲专门讨论了从功能级别到应用程序级别的所有级别软件中的版本控制概念。他甚至在演讲中特别提到了禁止使用 key 的概念,可以在 on youtube 找到。 。他说,它是有意设计的,以便只指定所需的 key 。禁止 key 确实没有什么好处,应该谨慎行事。

关于 :opt 键,我认为最初的答案仍然站得住脚——它是文档,实际上,它允许生成这些可选指定的键:

(s/def ::name #{"Bob" "Josh" "Mary" "Susan"})
(s/def ::height-inches (s/int-in 48 90))
(s/def ::person (s/keys :req-un [::name] :opt-un [::height-inches]))

(map first (s/exercise ::person))

; some generated data have :height-inches, some do not
({:name "Susan"}
 {:name "Mary", :height-inches 48}
 {:name "Bob", :height-inches 49}
 {:name "Josh"}

关于clojure - clojure.spec 中的禁止键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38131252/

相关文章:

scala - 如何在clojure中创建一个scala对象

maven - 将 Leiningen 与本地 M2 存储库一起使用

clojure.spec conform 抛出堆栈溢出异常

Clojure.spec:如何规范对随机变化敏感的数据结构?

clojure - 嵌套级别之间具有相互依赖值的 map 规范?

unit-testing - 为什么我不能使用 midje 来模拟使用弹弓的 throw+ 抛出的函数

clojure - 这个 "#"在这个 Clojure 上下文中是什么意思?

clojure - 什么是 Clojure 规范?

testing - 如何在 Lazytest 'describe' 测试中重新绑定(bind) var?

clojure - :pre & :post defn conditions become obsolete after core.规范是否被引入?