我有一个 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])}
我可以在运行时使用这些规范中的任何一个来验证 using s/valid?
,除了那个project-spec/project
。那一个要求所有其他人都在全球规范注册表中注册才能正常工作。当我尝试使用简单doseq
函数注册规范时,如果失败,因为我将局部变量传递给s/def
宏并且在扩展宏之前它不会将变量解析为值。
(doseq [[name spec] spec-map]
(s/def name spec))
在将变量传递给 s/def 宏之前,我尝试创建宏来评估变量,但是那个失败并带有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
但规范验证失败。
(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))
有什么方法可以实现我想做的事情吗?还是我误解了一些明显的东西?任何帮助表示赞赏!