glt*_*lts 4 clojure clojure.spec
我使用Clojure规范来规范一个简单的数据结构:
{:max 10
:data [[3 8 1]
[9 0 1]]}
Run Code Online (Sandbox Code Playgroud)
该:data值是从零到包含:max值的区间中的等大小整数向量的向量.我用以下规格表达了这个:
(s/def ::max pos-int?)
(s/def ::row (s/coll-of nat-int? :kind vector?, :min-count 1))
(s/def ::data (s/and (s/coll-of ::row :kind vector?, :min-count 1)
#(apply = (map count %))))
(s/def ::image (s/and (s/keys :req-un [::max ::data])
(fn [{:keys [max data]}]
(every? #(<= 0 % max) (flatten data)))))
Run Code Online (Sandbox Code Playgroud)
自动发电机适用于前三个规格,但不适用::image.(s/exercise ::image)100次尝试后总是失败.
我试图创建一个自定义生成器,::image但没有管理.我不知道如何表达跨越嵌套结构层的:max约束(键约束其他地方的向量中的值).
是否可以创建一个生成::images 的Clojure spec/test.check生成器?
非也!这里的关键是创建域的模型.在这里,我认为模型是max,col-size和row-size.这足以生成一个有效的例子.
所以像这样:
(def image-gen
(gen/bind
(s/gen (s/tuple pos-int? (s/int-in 1 8) (s/int-in 1 8)))
(fn [[max rows cols]]
(gen/hash-map
:max (s/gen #{max})
:data (gen/fmap #(into [] (partition-all cols) %)
(s/gen (s/coll-of (s/int-in 0 (inc max))
:kind vector?
:count (* rows cols))))))))
Run Code Online (Sandbox Code Playgroud)
首先,我们生成一个元组[<max-value> <rows> <cols>].所述gen/bind然后返回一个新的发生器创建在所需形状的地图.我们gen/fmap在里面嵌套以构建所有随机数据值的向量,然后将其重新塑造成适当的嵌套向量形式.
然后,您可以将其与图像组合:
(s/def ::image
(s/with-gen
(s/and (s/keys :req-un [::max ::data])
(fn [{:keys [max data]}]
(every? #(<= 0 % max) (flatten data))))
(fn [] image-gen)))
Run Code Online (Sandbox Code Playgroud)
一个有趣的事情需要注意的是,我将行和列限制为不超过7,因为生成器可以尝试生成非常大的随机随机样本值.需要绑定这样的东西在自定义生成器中很常见.
通过更多的努力,您可以从这些规格和生成器部件中获得更多的重用.