首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >test.check中的循环与状态管理

test.check中的循环与状态管理
EN

Stack Overflow用户
提问于 2016-10-31 07:22:00
回答 1查看 188关注 0票数 3

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

它已经极大地帮助了生成器--相当于Clojure的循环/重复或约简,这样在一个迭代中产生的值就可以存储在某个聚合的值中,然后在后续的迭代中访问。

需要这样做的一个简单示例是编写一个生成器,用于将集合分割成精确的X分区,每个分区在零元素和Y元素之间,然后将元素随机分配给任何分区。(请注意,test.chuckpartition函数不允许指定X或Y)。 如果您通过循环遍历集合来编写这个生成器,那么这将需要访问以前迭代期间填充的分区,以避免超过Y。

有人有什么想法吗?我发现了部分解决办法:

  • letbind允许您生成一个值,然后在稍后重用该值,但它们不允许迭代。
  • 您可以使用tuplebind函数组合遍历以前生成的值的集合,但是这些迭代不能访问以前迭代期间生成的值。 (defn bind-each [k coll] (apply tcg/tuple (map (fn [x] (tcg/bind (tcg/return x) k)) coll))
  • 您可以使用原子(或挥发物)来存储和访问以前迭代期间生成的值。这是可行的,但它是非常不可关闭的,特别是因为在返回生成器之前需要reset!原子/易失性元素,以避免它们的内容在生成器的下一个调用中被重用。
  • 由于生成器的bindreturn功能类似于monad,这意味着使用monad库(如Cats和State )。然而,在Cats 2.0中删除了State monad (因为据称它不适合Clojure),而我所知道的其他支持库没有正式的Clojurescript支持。此外,当在自己的库中实现一个State时,Jim -Clojure的monad专家之一--似乎警告说,State monad的使用与test.check的收缩(参见http://www.clojure.net/2015/09/11/Extending-Generative-Testing/底部)不兼容,这大大降低了使用test.check的优点。
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-10-31 13:45:24

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

代码语言:javascript
复制
(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子集序列(我意识到这并不完全是您的示例,但我认为可以对其进行调整以适应),您可以这样做:

代码语言:javascript
复制
(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))))))
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40337996

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档