请分享您的想法,参与 Clojure 2024 年调查!

欢迎!请查看 关于 页面以了解更多此平台的信息。

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/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)


在我的默认设计中,这可能会挂起,原因和这段代码可能挂起的原因相同


(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
参考:[TCHECK-15](https://clojure.atlassian.net/browse/TCHECK-15)(由 gfredericks 提出)
...