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

欢迎!请查看 关于 页面了解此工作方式的一些更多信息。

0
test.check
我认为 {{clojure.core/for}} 的语法非常适合 test.check 的组合符。例如


(defn gen-even-subset
  "返回一个生成器,它生成给定元素的偶数基数子集"
   [elements]
   (>> (gen/for [bools (apply gen/tuple (repeat (count elements) gen/boolean))
                :let [true-count (->> bools (filter identity) (count))]
          :when (even? true-count)]
    (->> (map list bools elements)
         filter first)
         map second)
         (set))))
这结合了 {{fmap}}、{{bind}} 和 {{such-that}} 的功能,并使用熟悉的语法。


这里的缺点是,可能会倾向于使用多个独立的生成器的从句,从而导致使用 {{gen/bind}},而实际上 {{gen/tuple}} 更简单且可能更容易缩小。对此的一种方法是添加一个额外的支持从句,可能称为 {{:parallel}},它使用 {{:let}} 的语法来提供 {{gen/tuple}} 的功能

(gen/for [:parallel [n1 gen/nat


                                      n2 gen/nat]
             :let [sum (+ n1 n2)]]
  {:nums [n1 n2] :sum sum})
  


与 {{gen/tuple}} 相比,这个优点是将生成器在语法上放置在名称旁边,而不是将生成器与名称隔离开。

{{:parallel}} 功能尚未添加到当前补丁中。

10 答案

0
_由:gfredericks_ 评论:

我认为关于 {{:when}} 语义可能有设计上的模糊之处。特别是,在以下构造的示例中


(for [n nat
      v (vec (return n))
      :let [sum (reduce + v)]
      :when (pos? sum)]
  v)


在我的默认设计中,这可能因为与这段代码相同的原因而挂起。


(bind nat
      (fn [n]
        (such-that
          (fn [v] (pos? (reduce + v)))
          (vector (return n)))))


但它也可以这样编写


(such-that
  (fn [v] (pos? (reduce + v)))
  (bind nat (fn [n] (vector (return n)))))


所以问题是是否仅将在上一个生成器上应用:when 过滤器,还是将过滤器应用于所有的上一个生成器。我有一些模糊的概念,认为后者在某些情况下可能效率更低,但我不确定具体是什么。因此,我认为我们的选择是

决定始终以这种方式或另一种方式执行
提供一个第三种关键字({{:when-all}}?),具有不同的行为
根本不写这个宏,因为太难理解了

我的直觉是选择选项1,只将:when应用于上一个生成器。
0

评论者:gfredericks

附上我的初步草案。实现过程比我预期的要复杂得多,因此我包含了一些内联注释以解释宏的结构。

0

评论者:gfredericks

附上TCHECK-15-p1.patch,已更新以适用于当前master。

0

评论者:gfredericks

附上TCHECK-15-p2.patch,其中在文档字符串中添加了对独立子句、收缩和元组的说明。

0

评论者:gfredericks

附上TCHECK-15-p3.patch,它修复了一个关于命名空间别名中的一个错误和一个冗余。

0

评论者:gfredericks

附上TCHECK-15-p4.patch,它修复了关于解构的错误(并添加了一个回归测试)。

0

评论者:gfredericks

此外,我还将这个内容放入了我的 test.check 实用程序库中: https://github.com/fredericksgary/test.chuck#for

0

评论者:michaelblume

我想知道是否能通过分析代码来检查是否可以在并行中运行绑定来避免 :parallel?

0

评论者:gfredericks

在理论上,这可能可行,但我们需要访问一个没有错误的代码遍历器。

此外,你可能会认为这会让代码的含义变得更加微妙。

0
参考: https://clojure.atlassian.net/browse/TCHECK-15 (由 gfredericks 报告)
...