我有地图,我想用它来验证在运行时我的要求是这样clojure.specs的:注册clojure.specs
{::num-id int?
:project-spec/id ::num-id
:project-spec/name (s/and string? #((< (count %) 24)))
:project-spec/project (s/keys :req-un [:project-spec/id :project-spec/name])}
我可以使用任何这些规范的运行,以验证使用s/valid?
,除了project-spec/project
之一。这需要所有其他人在全球规格注册表中注册才能正常工作。当我尝试使用简单doseq
函数注册规范时,如果失败,因为我将局部变量传递给s/def
宏,并且在扩展宏之前它不会将变量解析为该值。
(doseq [[name spec] spec-map]
(s/def name spec))
我试图创建宏传递他们的S/DEF宏之前EVAL变量,而是一个失败CompilerException java.lang.UnsupportedOperationException: Can't eval locals
。
(defmacro reg-spec
[name spec]
`(s/def ~(eval name) ~(eval spec)))
(doseq [[name spec] spec-map]
(reg-spec name spec))
我想的最后一件事是传递给s/def
时EVAL变量,但失败规范验证。
(s/def (eval spec-name) (eval spec-spec))
CompilerException java.lang.AssertionError: Assert failed: k must be
namespaced keyword or resolvable symbol (c/and (ident? k) (namespace k))
有没有什么方法可以实现我想要做的?或者我误解了一些明显的东西?任何帮助表示赞赏!
我想要达到的目标是重用无论是在应用程序的ClojureScript Clojure的和部分规格,我想有机会获得在运行,所以我可以做符合和验证。我也想重用它们来处理这些数据的函数。因此,将它们作为地图使用起来很方便,但我正在努力将它们从地图注册到全局注册表。 –
此外,即使您放置了未命名空间的'req-un'键,您仍然需要在其中提供名称空间键,因此spec可以验证与键对应的值。 –
@SergeyShvets查看[这篇文章](http://blog.cognitect.com/blog/2017/3/24/3xeif9bxaom78qyzwssgwz1leuorh4#sharing-specs-across-the-front-and-back-end)。我认为它确切地描述了你想要在CLJ/CLJS中重复使用规范的工作。另外,我不确定将规格存储在映射中与仅在命名空间中对它们进行定义相比具有什么优势。 –