gpt4 book ai didi

clojure - test.check 中的循环和状态管理

转载 作者:行者123 更新时间:2023-12-02 12:01:18 24 4
gpt4 key购买 nike

随着 Spec 的引入,我尝试为我的所有函数编写 test.check 生成器。这对于简单的数据结构来说很好,但对于具有相互依赖的部分的数据结构来说往往会变得困难。换句话说,需要在生成器内进行一些状态管理。

拥有 Clojure 的循环/递归或归约的生成器等价物已经有很大帮助,这样在一次迭代中生成的值可以存储在某个聚合值中,然后可以在后续迭代中访问该聚合值。

One simple example where this would be required, is to write a generator for splitting up a collection into exactly X partitions, with each partition having between zero and Y elements, and where the elements are then randomly assigned to any of the partitions. (Note that test.chuck's partition function does not allow to specify X or Y).

If you write this generator by looping through the collection, then this would require access to the partitions filled up during previous iterations, to avoid exceeding Y.

有人有什么想法吗?我找到的部分解决方案:

  • test.check 的 letbind 允许您生成一个值,然后在以后重用该值,但它们不允许迭代。

  • 您可以使用 tuplebind 函数的组合来迭代先前生成的值的集合,但这些迭代无法访问这些值在之前的迭代中生成。

    (defn bind-each [k coll] (apply tcg/tuple (map (fn [x] (tcg/bind (tcg/return x) k)) coll))

  • 您可以使用原子(或 volatile )来存储和访问先前迭代期间生成的值。这可行,但非常不符合 Clojure 风格,特别是因为您需要在返回生成器之前重置原子/ volatile ,以避免它们的内容在生成器的下一次调用中被重用.

  • 生成器由于其 bindreturn 函数而类似于 monad,这暗示了将 Cats 等 monad 库与 State 结合使用单子(monad)。然而,State monad 在 Cats 2.0 中被删除(因为据称它不太适合 Clojure),而我知道的其他支持库没有正式的 Clojurescript 支持。此外,当在自己的库中实现 State monad 时,Jim Duey(Clojure 的 monad 专家之一)似乎警告说 State monad 的使用与 test.check 的收缩不兼容(请参阅 http://www.clojure.net/2015/09/11/Extending-Generative-Testing/ 的底部),这显着降低了使用 test.check 的优点。

最佳答案

您可以通过将gen/let(或等效的gen/bind)与显式递归相结合来完成您所描述的迭代:

(defn make-foo-generator
[state]
(if (good-enough? state)
(gen/return state)
(gen/let [state' (gen-next-step state)]
(make-foo-generator state'))))

但是,如果可能的话,值得尝试避免这种模式,因为每次使用 let/bind 都会破坏收缩过程。有时可以使用gen/fmap重新组织生成器。例如,要将集合划分为一系列 X 子集(我意识到这与您的示例并不完全一样,但我认为可以对其进行调整以适应),您可以执行以下操作:

(defn partition
[coll subset-count]
(gen/let [idxs (gen/vector (gen/choose 0 (dec subset-count))
(count coll))]
(->> (map vector coll idxs)
(group-by second)
(sort-by key)
(map (fn [[_ pairs]] (map first pairs))))))

关于clojure - test.check 中的循环和状态管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40337996/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com