use*_*234 7 clojure clojure.spec
我刚看到Rich关于clojure.spec 的一次谈话,并且真的想试试我的项目.我正在编写一系列使用eclipse CDT库解析C代码的工具,我想说明我的函数接受并发出AST对象.
我认为可以为一个函数编写一个非常基本的规范,它接受AST的根并发出所有树的叶子,如下所示:
(import '(org.eclipse.cdt.core.dom.ast IASTNode))
(require '[clojure.spec :as s])
(defn ast-node? [node] (instance? IASTNode node))
(s/def ::ast-node ast-node?)
(s/fdef leaves :args ::ast-node :ret (s/coll-of ::ast-node))
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试练习代码时,(s/exercise leaves)我收到一个错误:
Unable to construct gen at: [] for:
xxx.x$leaves@xxx
#:clojure.spec{:path [], :form #function[xxx.xxx/leaves], :failure :no-gen}
Run Code Online (Sandbox Code Playgroud)
如何为Java对象编写自定义生成器以完全规范和运用我的代码?
Ale*_*ler 11
您可以使用s/with-gen将自定义生成器附加到规范.您需要编写一个生成所需节点变体的生成器.您可能会发现每个节点类型编写一个生成器然后将它们组合起来更容易,或者使用s/or或者可能通过使用类似的东西s/multi-spec(这将使其对扩展开放).
编写生成Java对象的生成器的示例如下所示:
(s/def ::date
(s/with-gen #(instance? java.util.Date %)
(fn [] (gen/fmap #(java.util.Date. %) (s/gen pos-int?)))))
Run Code Online (Sandbox Code Playgroud)
fmap接受一个函数并将其应用于您给它的生成器的每个结果.如果你有一个带有多个值的构造函数的Java对象,你可以使用像这样的源生成器(s/gen (s/tuple int? string? int?)).