我认为 {{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}} 功能尚未添加到当前补丁中。