我认为 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)
\n(->> (map list bools elements)
Bad indent.
(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}} 功能尚未添加到当前的补丁中。