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

欢迎!请参阅关于页面了解此网站的工作原理。

+1投票
Spec
使用由一些嵌套在疑问符“? ”中的“cat”构成的spec调用{{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}} of a {{s/?}} 将引入一个额外的嵌套级别。当子项是正则表达式时,我们正在消耗相同的“级别”的序列,因此unform不应该引入额外的级别。然而在其它情况下(非正则表达式操作),我们仍然可能会生成一个嵌套的集合。

上一个补丁太过激进:它会展开 {{s/?}} 的所有子-unform。这个补丁CLJ-2003-corrected.patch只在子操作是正则表达式时展开。

不幸的是,无法区分一个所需但可选的null和一个来自 {{s/?}} 的非匹配项。特别是,以下测试现在成立


(testing "s/?匹配null"}
  (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 报告)
...