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,请使用 such-that not nil 确保生成适当的序列。

22 个答案

0

评论由:gfredericks 监制

大多数集合生成器已经接受用于控制其大小的选项;您是否有特殊用例,那些控制不够充分?

0

评论由:m0smith 监制

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

我特别注意了基于字符串的生成器,因为我需要填充数据库表格,因此字符串必须与列定义匹配,例如非空(not null)和可变字符(varchar 15)。当我思考这个问题时,编写一个可组合的生成器来强制限制长度似乎比尝试修改所有产生序列相似结构的生成器更有意义。

简要检查了一下generators.cljc文件,发现列表、散列表以及基于数组的生成器都可以使用最小和最大选项。

0
by

评论由: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
by
_评论者: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]上的[测试 чук|https://github.com/gfredericks/test.chuck]更加放松。

0
by

评论由:m0smith 监制

你们更倾向于哪种方式?添加类似限制序列生成器长度的功能,还是创建(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-tries 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?为true,也总是返回不同的元素
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 监制

忽略那个补丁。我落后很多。新的补丁在路上。

0

评论由:m0smith 监制

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

0
评论者:m0smith_

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

(defn to-string
  "生成元素字符串,默认为字符串"
   {: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 ","})

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