2024 年 Clojure 调查问卷 中分享您的想法!

欢迎!有关如何使用本站,请参阅 关于 页面了解更多信息。

+1 投票
Spec
以下示例展示了在一个已校验的形式中,在未校验后不匹配任何形式,本应期望您可以重复校验 -> 未校验 -> 校验,并得到相同的结果。


(require '[clojure.core.specs])
(require '[clojure.spec :as s])

(s/def ::defn-macro (s/cat :type #{'defn} :definition :clojure.core.specs/defn-args))

(let [form '(defn foo "bar" ([a & b] a a c) ([a b] a))]

  (-> form
      (->> (s/conform ::defn-macro))) ;;=> {:type defn, :definition {:name foo, :docstring "bar", :bs [:arity-n {:bodies [{:args {:args [[:sym a]], :varargs {:amp &, :form [:sym b]}}, :body [a a c]} {:args {:args [[:sym a] [:sym b]]}, :body [a]}]}]}}

  ;; 未校验返回了函数定义,但是参数是以列表形式而不是向量形式
  (->> form
       (s/conform ::defn-macro)
       (s/unform ::defn-macro))  ;;=> (defn foo "bar" ((a (& b)) a a c) ((a b) a)))

  ;; 在未校验后再进行校验不再起作用
  (->> form
       (s/conform ::defn-macro)
       (s/unform ::defn-macro)
       (s/conform ::defn-macro)) ;;=> :clojure.spec/invalid

    )

7 个答案

+1 投票

对于特定的“必须既是集合又是向量的正则表达式”案例,无法使用 spec 1 实现,并使其适用于所有 conform、unform 和 gen。

在 spec 2 中,我们添加了对非流式 s/and(目前称为 s/and-,但该名称仍在变化,可能最终为 s/union 或其他)的支持,这是为了添加 s/cat 变体,同时还强制集合是向量或序列,即 s/catv 和 s/cats。

最终,我们将使用 spec2 重构核心.specs,并使用 s/catv 对 defn 参数向量进行处理,这将解决此问题。

0

由 jeroen 发布的评论

以下 gist 展示了代码的更好格式:https://gist.github.com/jeroenvandijk/28c6cdd867dbc9889565dca92673a531

0

评论者:lgs32a

这可以快速追溯到 :clojure.core.specs/arg-list,它被指定为一个 (s/and vector?)。在规范化时,它不会创建一个向量。

考虑一下,对于这种情况和类似的情况,一个 vcat 会很方便。

0

评论者:marco.m

你好,有什么新消息吗?

0

评论者:alexmiller

没有。

0

由 jeroen 发布的评论

发现了另一个问题

(->> '(foo (link: h0 & [h1])))
(s/conform :clojure.core.specs.alpha/defn-args)
(s/unform :clojure.core.specs.alpha/defn-args))
;#=> '(foo (link: h0 (& [h1])))

在这里,其余参数被封装在一个额外的列表中。我应该在哪里报告这个问题?

0
参考: https://clojure.atlassian.net/browse/CLJ-2021(由 jeroen 报告)
...