2024 Clojure 状态调查! 中分享你的想法。

欢迎!请参阅 关于 页面,以了解更多有关此作品的信息。

0
Spec

嗨,我在这里报告我认为是我在一周内遇到的第二个小问题,与 spec 仪表有关。

如果它已被报告为错误,请原谅我,但我基本上无法理解/预期的最后一个调用触发错误 - ::id-map 规格不需要对 ::other 执行检查。

(ns repro-spec.test
  (:require [clojure.spec.alpha :as s]
            [clojure.spec.test.alpha :as st]))

(s/def ::impl any?)
(s/def ::id string?)
(s/def ::other number?)

(s/def ::id-map (s/keys :req [::id]))

(s/fdef delete-impl
  :args (s/cat :impl ::impl
               :id-map ::id-map))

(defn delete-impl [_ id-map]
  (println (str "This deletes " (::id id-map)))
  id-map)

(st/instrument)

(delete-impl {} {::id "test"})
;; prints "This deletes test"

(delete-impl {} {::id "test" ::other "ignore me"})
;; Execution error - invalid arguments to repro-spec.test/delete-impl at (REPL:27).
;; "ignore me" - failed: number? at: [:id-map :repro-spec.test/other] spec: :repro-spec.test/other

是我做错了什么吗?

1 答案

0

这是有意为之,并在文档中有描述:https://clojure.org/guides/spec#_entity_maps

当在映射上进行一致性检查时,它会做两件事情 - 检查所需属性是否包含在其中,并检查每个注册键是否具有符合的值。我们稍后将看到可选属性为何有用。请注意,所有属性都通过键进行检查,而不仅仅是那些列在与 :req 和 :opt 键中的属性。 因此,一个裸的 (s/keys) 是有效的,并将检查映射的所有属性,而不检查哪些键是必需的或可选的。

(我强调)

确实在那里!TIL :D

你有没有什么关于它的原因?看起来 `s/keys` 可以允许“限制”你想要检查的范围 - 换句话说,只检查这些键 - 但接下来的检查似乎是对所有键都进行的?
我怀疑Alex更有资格对该问题进行评论,但我的理解是,有资格的Spec名称是为了给全局名称赋予全局意义,而s/keys是为了标识是否需要特定的键(:opt基本上是为了文档目的,表示“我也可能使用这些键”)。所需性与名称的全局意义是正交的。

注意,对于: req-un / :opt-un,这并不成立,因为那些键在映射中未经过资格验证,不具有全局意义--只有通过s/keys中名称的资格为(关联的有资格的Spec名称)指定的那些意义。
所需性与名称的全局意义是正交的。

感谢你的解释,这正是我所缺少的。全局事物确实会使独立推理更加困难(据我所知,可能是显而易见的)。我现在可以理解为什么`spec2`中的`select`会出现了。
你可能觉得阅读规范的理由和指南对回答这些问题有所帮助

* https://clojure.org/about/spec
* https://clojure.org/guides/spec
第一个链接很有用,谢谢。
...