请在 2024 年 Clojure 状态调查中分享您的想法!

欢迎!有关如何使用本站的更多信息,请查看关于页面。

+1
Spec
以下示例显示了一个符合后的形式,在解构后不再符合任何形式。我预计您可以无限重复 conform -> unform -> conform 操作并获得相同的结果。


(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 并使其对所有符合、解构和生成都是可用的实际上是不可能的。

在规范2中,我们增加了对非流式s/和(目前称为s/和-,但这个名字仍在变化,最终可能成为s/联合或其他名称)的支持,这对于添加s/cat变体以强制coll为向量或序列(如s/catv和s/cats)是必需的。

最终,我们将重新设计core.specs使用spec2,并使用s/catv作为定义参数向量,这将解决此问题。

0

评论人:jeroen

此代码片段显示了上述代码,格式更好 https://gist.github.com/jeroenvandijk/28c6cdd867dbc9889565dca92673a531

0

评论人:lgs32a

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

考虑一下,vcat对这种情况和类似情况会很好。

0

评论人:marco.m

你好,有什么新消息吗?

0

评论人:alexfiller

没有。

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
by
参考: https://clojure.atlassian.net/browse/CLJ-2021(由jeroen报告)
...