欢迎!请参阅关于页面了解有关此信息的更多情况。

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


(defn gen-even-subset
  "返回一个生成器,用于生成给定元素的偶数基数子集"
      "[elements]"
    [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/tuple}}和更容易剪枝时使用{{gen/bind}}。一种方法是为这种功能添加一个额外的支持子句,也许称为{{: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)


在我的默认设计中,这可能会崩溃,原因与这段代码崩溃的原因相同


(绑定 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
回答 by

评论者:gfredericks

附上我的初步草案。实现过程比预期的要复杂得多,所以我在宏的结构上添加了一些内联注释进行说明。

0
回答 by

评论者:gfredericks

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

0
回答 by

评论者:gfredericks

附上 TCHECK-15-p2.patch,在文档字符串中添加关于独立子句、收缩和元组的注释。

0
回答 by

评论者:gfredericks

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

0
回答 by

评论者:gfredericks

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

0

评论者:gfredericks

同时,我也已经把这个添加到了我的测试工具库test.check中: https://github.com/fredericksgary/test.chuck#for

0

评论者:michaelblume

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

0

评论者:gfredericks

从理论上讲,这是可能的,但我们需要访问一个无错误的代码遍历器。

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

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