2024 年 Clojure 状态调查!(分享您的想法!

欢迎!请访问关于页面了解更多关于如何使用本网站的信息。

0
规范

大家好,我在这里来报告我认为是我本周遇到的第二次奇遇,关于 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) 是有效的,并且将在不检查哪些密钥是必需的或可选的的情况下检查映射的所有属性。

(我的强调)

确实如此!学到了:D

你们知道这其中的理由吗?`s/keys`看起来可以“限制”你想要检查的范围——也就是说,只检查这些键——但是最终的检查却是所有键都会被执行吗?
作者
我怀疑Alex更了解这个话题,但我的理解是,限定命名规范名是为了给予全局命名一个全局意义,而`s/keys`是用来标识是否需要特定的键。`:opt`主要是为了文档目的,表示“我也可能使用这些键”的意思。这种必须性是和名字的全局意义正交的。

请注意,对于`:req-un`和`:opt-un`来说,这并不是真的,因为这两个键在映射中是无界的,并且没有全局意义——只有`s/keys`中通过名称限定赋予它们的局部意义。
作者
> 这种必须性与名字的全局意义正交。

谢谢你的解释,这正是我之前所缺少的。全局的元素确实使得独立思考变得更加困难(个人意见,也许很明显)。现在我知道为什么`spec2`中的`select`等功能会出现了。
作者
你可能会发现阅读规范理由和指南对于回答这些问题有所帮助。

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