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) 来返回最大长度
需要小心返回与接收的类型相同的类型。
如果不接收序列,则将其视为一个元素序列处理。
如果最小值不是0,则使用 such-that not nil 来确保生成合适的序列。

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))都正常工作

有没有什么技巧可以让“string”工作?或者有没有更好的方法来修改string来接受多个参数?

0
_评论由gfredericks发表_

我认为没有一个干净的解决方案可以解决这个问题,这也是我没有在这里找到明显解决方案的原因之一。

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

事后的认识是,我不知道这是否是最好的选择,因为这很让人困惑。我向David MacIver询问了他在hypothesis (一个类似的python库) 中是如何处理这个问题的,他说他没有任何原始的生成器,只有返回生成器的函数(有时需要0个参数)。我喜欢这种方法的一致性,但这显然会破坏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 评论:

我对提出这个请求的思考。我们真的需要将字符串生成器的数量翻倍吗?更不用说其他像数组等东西了。

另一个想法是添加一个单独的新生成器,叫 to-string,它可以接受不同的字符生成器,并将其用作基于元素生成器生成字符串。


 (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
by

评论由:m0smith 提出

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

0
by

评论由:m0smith 提出

忽略该补丁。我的master版本太旧了。新的补丁正在路上

0
by

评论由:m0smith 提出

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

0
by
_由 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
by

评论由:gfredericks 提出

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

0
by
_由 m0smith 评论:

另外,对于to-string,clojure.string/join支持一个分隔符,可以轻易作为附加选项添加,如

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

如果这没问题,我将更新补丁。
...