使用Clojure Spec从递归定义生成 [英] Generating from recursive definitions with Clojure Spec

查看:82
本文介绍了使用Clojure Spec从递归定义生成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们考虑打Clo语法的Clojure Spec正则表达式

Let's consider a Clojure Spec regexp for hiccup syntax

(require '[clojure.spec :as spec])

(spec/def ::hiccup
  (spec/cat :tag        keyword?
            :attributes (spec/? map?)
            :content    (spec/* (spec/or :terminal string?
                                         :element  ::hiccup))))

精彩

(spec/conform ::hiccup [:div#app [:h5 {:id "loading-message"} "Connecting..."]])
; => {:tag :div#app, :content [[:element {:tag :h5, :attributes {:id "loading-message"}, :content [[:terminal "Connecting..."]]}]]}

直到您尝试根据规范为函数生成一些示例数据

until you try to generate some example data for your functions from the spec

(require '[clojure.spec.gen :as gen])
(gen/generate (spec/gen ::hiccup))
; No return value but:
; 1. Unhandled java.lang.OutOfMemoryError
;    GC overhead limit exceeded

是否可以重写规范以使其生成有效的生成器?还是我们必须在规范中附加一些简化的生成器?

Is there a way to rewrite the spec so that it produces a working generator? Or do we have to attach some simplified generator to the spec?

推荐答案

spec / *的意图recursion-limit * (默认值为4)是为了限制递归生成,使其可以正常工作。因此,要么在某些规范提示( * )之一中无法正常工作,要么您看到了快速增长在其他内容中(例如 map?或字符串)。不做任何修改,很难知道是什么问题。

The intent of spec/*recursion-limit* (default 4) is to limit recursive generation such that this should work. So either that's not working properly in one of the spec impls (* or or), or you are seeing rapid growth in something else (like map? or the strings). Without doing some tinkering, it's hard to know which is the problem.

这确实为我产生了(一个非常大的例子):

This does generate (a very large example) for me:

(binding [spec/*recursion-limit* 1] (gen/generate (spec/gen ::hiccup)))

我确实看到了几个基数很大的区域,即使在一个例子中- * 和生成的属性 map的大小?。两者都可能受到进一步限制。将这些部分进一步细分为更细粒度的规范,并在必要时提供覆盖生成器将是最容易的(属性映射只能使用 map-of :gen-max )。

I do see several areas where the cardinalities are large even in that one example - the * and the size of the generated attributes map?. Both of those could be further constrained. It would be easiest to break these parts up further into more fine-grained specs and supply override generators where necessary (the attribute map could just be handled with map-of and :gen-max).

这篇关于使用Clojure Spec从递归定义生成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆