2024 Clojure状态调查中分享您的想法!

欢迎!有关此功能的工作原理,请参阅关于页面以获取更多信息。

0
test.check

有许多生成器返回序列(列表、向量、元组、映射、字符串等)。有时对生成的序列设置大小限制(无论是最小还是最大)是有用的。最好有一个接受序列生成器并确保序列为特定长度的生成器。以下是一些示例:
(of-length min max gen)
(of-max-length max gen) => (of-length 0 max gen)
(of-min-length min gen) => (of-length min nil gen)

of-length会检查生成序列的长度。如果过长,则使用(take min (cycle s))来扩展序列长度。
如果过长,则使用(take max s)来返回最大长度。
需要小心返回它接收到的相同类型。
如果没有接收到序列,则将其视为一个元素序列。
如果min不是0,则使用not nil such-that确保生成正确的序列。

22 答案

0

评论由:gfredericks

大多数收集生成器已经接受选项来控制其大小;是否有任何您认为这些控制不充分的用例?

0

评论由:m0smith

我完全忽略了那些接受:min和:max选项的生成器。

特别地,我正在考虑基于字符串的生成器,因为我需要填充数据库表,所以字符串必须与列定义匹配,如非空和 varchar (15)。当我思考这个问题时,好像编写一个可组合的生成器来强制长度限制比尝试为所有生成有序结构类型的生成器进行反向改造更有意义。

简要检查 generators.cljc 显示列表、哈希表和基于数组的生成器都可以使用最小和最大选项。

0

评论由:m0smith

如果我尝试将字符串从一个 def 更新到 defn,以允许为大小参数提供多个参数,如下所示

(defn string ([] (fmap clojure.string/join (vector char))) ([size] (fmap clojure.string/join (vector char size))) ([min max] (fmap clojure.string/join (vector char min max))))

那么 (sample string) 就不再起作用,但 (sample (string)) (sample (string 5)) (sample (string 3 7)) 都可以

有什么技巧可以使“字符串”起作用吗?或者有没有更好的方法来修改字符串以接受多个参数?

0
评论者:gfredericks

我认为目前没有任何干净的方法来解决您提到的问题,这也是为什么我看不到这里有一个明显的解决方案。

我在创建 {{large-integer}} 和 {{double}} 生成器时遇到了这个问题,并决定创建两个生成器:{{large-integer}} 是具有默认行为的生成器,而 {{large-integer*}} 是一个接受选项并返回生成器的函数。

事后看来,我不知道这是否是最好的选择,因为它的确很令人困惑。我向 David MacIver 咨询了他在 hypothesis(一个类似的 Python 库)中如何处理此问题,他说他没有 *任何* 原始生成器,只有返回生成器的函数(有时不带参数)。我喜欢这种方法的统一性,但是它显然会对 test.check(尽管有一些可以保留向后兼容性的小巧技巧)造成重大的破坏性改变。

这个问题比这个工单更大一些。关于你提供的代码,我认为我更喜欢更接近于 {{gen/set}} 的 API,使用一个选项映射,而不是位置参数。

现在让我思考这个问题,我开始专注于这个想法:一个为了清理大量不一致性而使用改为保持向后兼容性的一些巧妙的大的破坏性 API 改变。但再次强调,这比这个工单更大。

如果我们不能提出一个干净且短期的解决方案,那么我在 [test.chuck|https://github.com/gfredericks/test.chuck] 上的接受标准就更为宽松了 ☺。

0

评论由:m0smith

你更喜欢哪一个?添加类似于 of-length 的东西来限制现有的序生成器,还是创建 (def string ...) 和 (defn string*)?我在完成 TCHECK-97 的 Unicode 实现的同时也会跟随我们决定的任何模式。

0

评论由:gfredericks

我们难道没有至少三种字符串生成器吗?你是在考虑为每个生成器提供替代方案吗?

0
_m0smith_ 发表的评论

我提出这个请求的初衷。我们真的想将字符串生成器的数量翻倍吗?更不用说数组等其他事情。

另一个想法是添加一个新生成器,bff,它可以接受不同的字符生成器,并用它来根据元素生成器创建字符串


 (defn to-string
   ([element-gen] (to-string element-gen {})))
   ([element-gen [{:keys [num-elements min-elements max-elements max-tries ] :or {num-elements nil min-elements 0 max-elements nil max-retries 10}}]
                   (fmap clojure.string/join (vector char-gen ==apply-options==))))


我省略了处理选项的代码,但希望你能理解其原理。

可以像  (to-string char {:min-elements 5 :max-elements 10})  或 (to-string char-ascii {:num-elements 5})  那样调用

这样就可以添加新的字符生成器,它们可以很容易地转换为字符串。
0
_m0smith_ 发表的评论

看起来,coll-distinct-by 几乎完美地做到了我所需要的事情,除了 allow-dups? 标志没有按我预期的进行。

(sample (coll-distinct-by [] identity true  false (elements [\a \b \c \d \e ]) {:num-elements 4})) 即便 allow-dups? 为真也总是返回不同的元素
0

评论由:gfredericks

coll-distinct-by 相对较专用,可能在此不相关。

我认为你可以非常容易地将 (link: num-elements min-elements max-elements) 转换为 gen/vector 方法所需的参数。 max-retries 不适用。

类似于 {{to-string}} 的东西可能很好,特别是如果它与你在 TCHECK-97 上思考的内容相匹配(例如,TCHECK-97 为 {{to-string}} 提供参数)。

0

评论由:m0smith

使用git --no-pager diff master feature/TCHECK-99生成的补丁,位于https://github.com/m0smith/test.check.git

0

评论由:m0smith

忽略那个补丁。我和master相差太远了。新的补丁正在路上。

0

评论由:m0smith

TCHECK-99-2.patch是在将test.check与我分支同步后生成的。应该是最新的。

0
_m0smith_ 发表的评论

我还想到了如何允许一个函数像生成器一样被处理。  给一个函数添加一个:generator-factory元数据,比如

(defn to-string
  "生成由element-gen生成的字符串,默认为字符"
   {:generator-factory to-string}
   ([] (to-string char {})))
   ([element-gen] (to-string element-gen {})))
   ([element-gen [{:keys [num-elements min-elements max-elements]}]
                   (fmap clojure.string/join (vector char-gen ==apply-options==))))


生成器?可以更新为接受任何具有:generator-factory元数据的函数
call-gen可以更新为查找新的元数据,如果存在,则调用相关函数并使用结果作为生成器

0

评论由:gfredericks

是的,这基本上是我想保留向后兼容性的想法--元数据生成器将以某种方式附加某些类型的弃用警告。

0
_m0smith_ 发表的评论

另外,在to-string中,clojure.string/join支持一个分隔符,可以轻松地将其作为附加选项添加

(to-string int {:sep ","})

如果你同意,我将更新补丁。
...