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

欢迎!请访问关于页面获取更多关于本网站运作方式的信息。

+1
Spec
以下示例显示了一种情况,其中已符合的表单在进行unform后没有符合任何内容。我期望您可以持续重复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]}]}]}}

  ;; Unforming returns the function definition, but with the args in a list instead of a vector
  (->> form
       (s/conform ::defn-macro)
       (s/unform ::defn-macro))  ;;=> (defn foo "bar" ((a (& b)) a a c) ((a b) a)))

  ;; After unforming, conforming no longer works
  (->> form
       (s/conform ::defn-macro)
       (s/unform ::defn-macro)
       (s/conform ::defn-macro)) ;;=> :clojure.spec/invalid

    )

7 个答案

+1

对于“正则表达式必须也是向量的集合”的具体情况,使用spec 1很难实现,而且要它能在conform、unform和gen中一起工作。

In spec 2中,我们增加了对非流式s/and(目前称为s/and-,但这个名字还在变动,可能最终会成为s/union或其他称呼)的支持,这是添加s/cat变体所必需的,这些变体会额外强制集合是向量或序列,即s/catv和s/cats。

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

0

评论者:jeroen

这个片段展示了上述代码的更好格式: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 报告)
...