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

欢迎!有关如何工作的更多信息,请参阅关于页面。

+1
Spec
调用 {{conform}} 然后使用由嵌套在 {{?}} 中的 {{cat}} 组成的 spec 进行 {{unform}} 会使得结果多出一层嵌套


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

(let [spec (s/? (s/cat :foo #{:foo}))
      initial [:foo]
      conformed (s/conform spec initial)
      unformed (s/unform spec conformed)]
      [initial conformed unformed])
;;=> [[:foo] {:foo :foo} [(:foo)]]


仅使用 {{?}} 或 {{cat}} 独自使用时,这种行为不会发生


(let [spec (s/? #{:foo})]
  (s/unform spec (s/conform spec [:foo])))
;;=> [:foo]

(let [spec (s/cat :foo #{:foo})]
  (s/unform spec (s/conform spec [:foo])))
;;=> (:foo)


*补丁:* CLJ-2003-corrected.patch

10 个答案

0

评论由:pbrown 提供

我遇到了另一个额外的嵌套案例,当重复一个或多个序列并在开始或结尾处加上可选元素时,该元素的谓词也匹配另一端的元素

user=> (s/conform (s/+ (s/cat :k any? :v (s/? any?))) [:a 1 :b 2]) [{:k :a, :v 1} [{:k :b, :v 2}]]

我预期

`[{:k :a, :v 1} {:k :b, :v 2}] `

以下给出预期的结果

user=> (s/conform (s/+ (s/cat :k any? :v (s/? any?))) [:a 1 :b]) [{:k :a, :v 1} {:k :b}] user=> (s/conform (s/+ (s/cat :k keyword? :v (s/? int?))) [:a 1 :b 2]) [{:k :a, :v 1} {:k :b, :v 2}] user=> (s/conform (s/* (s/cat :k any? :v (s/? any?))) [:a 1 :b 2]) [{:k :a, :v 1} {:k :b, :v 2}]

0

alexmiller 评论:

Phil,我认为你的例子是不同的问题,你应该为那个问题提交新的jira。

0

alexmiller 评论:

好吧,也许我收回刚才的话,它们可能有关联。

0

bbloom评论:

我在尝试理解一些defn形式时遇到了这个问题。这里有一个例子

user=> (s/unform :clojure.core.specs/defn-args (s/conform :clojure.core.specs/defn-args '(f (link: & xs))))
(f ((& xs)))

0

[email protected]评论:

这似乎是所需的所有内容。

0
_favila_评论:

实际上,这个问题比 {{(? (cat ...))}} 更普遍。当子操作为正则表达式子操作时,s/? 的 {{s/unform}} 会引入一个额外的嵌套层级。当子操作是正则表达式时,我们正在消耗相同层面的序列,因此 unform 不应该引入额外的层级。然而,在其他情况下(非正则操作),我们仍然可能生成嵌套的集合。

之前的补丁过于激进:它解包了 {{s/?}} 的 **所有** 子-unform。这个补丁 CLJ-2003-corrected.patch 只在子操作是正则表达式时才进行解包。

不幸的是,我们无法区分期望但不必要的 nil 和 {{s/?}} 的非匹配。具体来说,以下测试现在成立


(testing "s/? 匹配 nil"
  (is (nil? (s/conform (s/? nil?) [nil])))
  (is (nil? (s/conform (s/? nil?) [])))
  (is (nil? (s/conform (s/? nil?) nil)))
  (is (= (s/unform (s/? nil?) nil) [])))


(我没有将这些测试添加到补丁中,因为我不确定它们是否应该成为 unform 合同的一部分。然而,它们是非常大的陷阱。)

我还为 {{s/?}} 的每个可能子操作添加了测试,除了 {{::s/accept}},我没有想到测试用例。(我不确定 {{::s/accept}} 是否真的在 {{s/op-unform}} 内可达?)
0

alexmiller 评论:

感谢您为此工作 - 我有机会时会查看。

0

评论者:favila

我不得不稍微修改我的补丁(相同的名称):其中有一个测试用例没有测试正确的内容。

0

评论者:favila

补丁因其他提交中加入的测试而无法干净地应用于master,补丁已重新基于master

0
参考: https://clojure.atlassian.net/browse/CLJ-2003 (由alex+import报告)
...