在<.panel 的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将不会检查最可能包含bug的值。

我现在处于这样的地位,感觉到有压力要重新实现s/every(使其全面)或者s/and(使其验证但不适配)- 但是这让我有点困惑,因为我刚刚假设我想要的功能将是常见的用例。我错过了什么吗?为什么在spec中没有包含不适配的s/and变体?

1 个答案

0

回答标题中的问题 - s/valid? 是用来检查一个值是否匹配一个特定的规范。s/conform 会告诉你一个值是如何匹配规范的(通过显示所选择的备选方案,并对规范的各个部分进行组件标记)。

关于 s/and 的问题,这长期以来一直在讨论是否应该包含流式 s/and 或非流式。两者都有很好的应用场景(这也在生成方面得到了体现)。在正在进行中的 spec2 规范中,我们已经包括了非流式的 s/and,目前命名为 s/and-(但这个名字是暂定的——可能最终会被命名为 s/union 或其他名字)。

关于 s/every,看起来您想要的是 s/coll-of,它可以符合所有元素。这两种情况都很有用(我们不希望无休止地检查无限的序列!)

关于确保具有特定语法(通过 cat)的向量的具体情况,这在宏中的确是一个相对常见的情况,但基本上是难以实现的。您发现了这一点,您想要一个非流式的 and!但在 spec2 中,我们已经以 s/catv 的形式提供了这个组合(就像 cat 一样,但限制于向量)。

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

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