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
第一个链接很有帮助,谢谢。
...