我有地圖,我想用它來驗證在運行時我的要求是這樣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中重複使用規範的工作。另外,我不確定將規格存儲在映射中與僅在命名空間中對它們進行定義相比具有什麼優勢。 –