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

如果尝试将from a def updates to a 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))仍然可以工作

有没有让“just string”正常工作的技巧?或者是否有更好的方式让string接受多个参数?

0投票
by
_Comment made by: gfredericks_

我认为没有干净的方法来解决你提出的问题,这也是我看不到明显解决方案的一个原因。

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

事后看来,我不知道这是否是最好的选择,因为它是令人困惑的。我曾向David MacIver询问他在hypothesis (/python类库中是如何处理这个问题的,他说他没有任何原始的生成器,只有返回生成器的函数(有时带0个参数)。我喜欢这种方法的统一性,但显然这会给test.check带来巨大的破坏性变化,尽管也有一些巧妙的方法可以保持向后兼容性。

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

现在你让我思考这个问题,我开始沉迷于修改API的想法,使用一些技巧来在几个版本中保留回滚兼容性,以清理大量不一致性。但同样,这比这个票据更大。

如果我们不能想出一个干净的短期方法,我在[https://github.com/gfredericks/test.chuck] (test.chuck)的接受标准就会更加宽松了。

0投票
by

评论者: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?是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

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

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

是的,这基本上是我为了保持向后兼容的构想——元数据生成器将附带某种形式的已弃用警告。

0投票
_评论者:m0smith_

此外,对于 to-string 和 clojure.string/join,我们还可以支持一个分隔符,例如作为一个额外选项添加:

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

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