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

欢迎!请查看关于页面以了解此功能的更多信息。

0
Spec

我在尝试使用spec,但对于其中一部分设计不太理解。似乎没有很好的机制来表示“该值同时满足一系列spec”。

  • clojure.core中的and无助于解决问题,因为在这种情况下s/explain不会深入探究具体哪个spec数据结构没有满足。

  • s/and实际上是一系列转换,逻辑值取决于参数的顺序。我不想处理这种风险。我提供了一个类似的愚蠢示例,就像我曾经被咬到的那样

开始于

(s/def :example/s1 vector?)
(s/def :example/s2 vector?)
(s/def :example/spec (s/and :example/s1 :example/s2))
(s/valid? :example/spec [1 2 3]) ; => true

然后将:example/s1改为

(s/def :example/s1 (s/cat :a integer? :b integer? :c integer?))

现在

(s/valid? :example/spec [1 2 3]) ; => false

这使我在尝试调试一个spec的情况下处于困境;我不想再次处于这种情况。如果spec更为错综复杂,对我来说甚至不清楚如何开始,所以我更愿意避免完全在过程中转换/规范数据的功能,除非这显然是必需的。

  • s/every在通用方面似乎非常不安全——尽管名字如此,它并没有检查spec是否对每个条目都为真。我有扩展长向量的函数以及基于s/every的spec将特别不会检查最有可能包含错误值的条目。

我处于需要重新实现s/every(以实现全面)或s/and(以验证但不规范)的位置——但这对我来说有些令人困惑,因为我曾经以为我所需要的是通用用例。我错过了什么吗?为什么在spec中没有包含一个不规范的s/and变体呢?

1答案

0

回答标题中的问题 - s/valid? 用于检查一个值是否与指定相匹配。s/conform 会告诉您一个值是如何与指定相匹配的(通过显示选择的替代方案并对指定的部分使用组件进行标记)。

关于 s/and,这是关于是否包含流动 s/and 或非流动 s/and 的长期争论。两者都有很好的用例(生成方面也与此相关)。在当前的开发规范 spec2 中,我们已经包含了一个非流动 s/and,目前称为 s/and-(但此名称是试探性的——最终可能被称为 s/union 或其他名称)。

关于 s/every,听起来您想使用 s/coll-of,它使所有元素都符合规范。这两种情况都很有用(不想逐个检查无限序列!)。

关于通过 cat 确保具有特定语法(通过 cat)的向量的特定情况,这在宏中是一个相对常见的情况,基本上不可能从当前组件中获得组合并使 conform、gen、explain 和 unform 正确执行。正如您发现的那样,您想要非流动 s/and!但我们已经将该组合提供为 spec2 中的 s/catv(就像 cat 一样,但限制为向量)。

https://github.com/clojure/spec-alpha2/wiki/Differences-from-spec.alpha#nonflowing-sand--new

谢谢!很抱歉,问题在草案中有所偏离。
...