请在 2024 年 Clojure 调查! 分享您的看法。

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

+1 投票
Spec
使用包含一些嵌套在某个 {{?}} 中的 {{cat}} 的规范,调用 {{conform}} 然后调用 {{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

我在弄懂一些定义表单的过程中遇到了这个问题。以下是一个例子

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/unform}} 将引入一个额外的嵌套级别。当子操作是正则表达式时,我们正在消耗相同的 “级别” 的序列,因此 unform 不应该引入一个额外的级别。然而在其它情况下(非正则表达式操作),我们可能仍然会产生一个嵌套的集合。

之前的补丁过于激进:它解包了 {{s/?}} 的所有子 unforms。这个补丁 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](https://clojure.atlassian.net/browse/CLJ-2003)(由 alex+import 报告)
...