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

有没有什么技巧可以让“字符串”本身正常工作?或者是否有更好地修改字符串以接受多个参数的方法?

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
by

由m0smith发起的评论

您更喜欢哪种?添加类似于 of-length 的东西来限制现有的序列生成器,还是创建 (def string ...) 和 (defn string* ...)?由于我刚刚完成了 TCHECK-97 的 Unicode 实现工作,所以我将遵循我们决定的任何模式。

0
by

由gfredericks发起的评论

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

0
by
评论者: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
by
评论者: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
by

由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发起的评论

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

0

由m0smith发起的评论

忽略那个补丁。我master版本过时了。新的补丁即将到来

0

由m0smith发起的评论

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

0
评论者:m0smith

我还想到了一种允许函数像生成器一样被对待的方法。在函数如下面添加 :generator-factory 元数据:

(defn to-string
  "生成元素-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发起的评论

是的,这基本上就是我想保持向后兼容性的方法 -- 元数据生成器会以某种方式附上 depreciation 警告。

0
评论者:m0smith

此外,在 toString 中,clojure.string/join 支持分隔符,我们可以轻松地将它作为附加选项添加,如

(toString int {:sep ","})

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