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