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(以验证但非符合)的位置——但对我来说有点困惑,因为我刚刚假设我所想要的将是通用情况。我遗漏了什么?为什么没有包括s/and的非符合变体在spec中?

1 答案

0

回答标题中的问题 - s/valid?用于检查一个值是否符合规范。s/conform告诉我们一个值是如何符合规范的(通过显示选择了哪个选项,并对规范的不同部分使用组件进行标注)。

关于s/and,这是关于是否包含流动s/and或非流动s/and的长期争论。两者都有很好的用例(而且生成方面也涉及其中)。在wip规范2中,我们已经包含了一个非流动的s/and,目前称为s/and-(但这个名称是暂定的——最终可能被称为s/union或其他名称)。

关于s/every,听起来您想要s/coll-of,它符合所有元素。这两种情况都很有用(不希望在无限的序列中详尽无遗地检查!)。

关于确保使用特定语法(通过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

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