我希望根据我从请求中提取的一些数据生成一组规范。我想根据我收到的数据动态定义一些规范。
(def my-key :frame-data/pretty_name) ;;imagine this and the validator aren't hardcoded
(def validator string?)
(s/def my-key validator?) ;; defines my-ns/my-key, instead of `:frame-data/pretty_name.
(s/describe my-key) ;; string? ;;which sorta works, but its looking up `my-ns/my-key` instead of :frame-data/pretty_name
我的目标是拥有一个看起来像我写的规范:
(s/def :frame-data/pretty_name string?)
我是 clojure 新手,所以我不太清楚如何做到这一点,但我尝试了一些方法:
(s/def (eval my-key) validator) ;;Assert Failed: k must be a namespaced keyword or resolveable symbol
(definemacro def-spec [key validator]
'(s/def ~key ~validator))
(def-spec my-key validator) ;; my-ns/my-key ;; returns the same as earlier
还有很多变体,但我不确定如何动态定义规范,但感觉应该如此。
最佳答案
您可以在 clojure.spec.alpha/def
表单上执行宏扩展来查看它扩展为的内容:
(macroexpand `(s/def :frame-data/pretty_name string?))
;; => (clojure.spec.alpha/def-impl (quote :frame-data/pretty_name) (quote clojure.core/string?) string?)
或者查看source code clojure.spec.alpha/def
。
然后编写您自己的宏,不引用规范键以便对其进行评估:
(defmacro defspec [k spec-form]
`(s/def-impl ~k (quote ~spec-form) ~spec-form))
示例:
(defspec my-key validator)
(s/valid? my-key "abc")
;; => true
(s/valid? my-key 123)
;; => false
(s/describe my-key)
;; => validator
如果您不喜欢 (s/describe my-key)
返回 validator
,请尝试替换 (quote ~spec-form)
在宏定义中只用~spec-form
,也许你会更喜欢这样。
关于clojure - 如何动态定义规范?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69197996/