2017-10-13 8 views
2

나는이 같은 런타임 내 요청의 유효성을 검사하는 데 사용할 clojure.specs의지도를 가지고 project-spec/project을 제외한 s/valid?을 사용하십시오. 그 하나는 모든 다른 사람들이 제대로 작동하려면 글로벌 사양 레지스트리에 등록해야합니다. 간단한 doseq 함수를 사용하여 스펙을 등록하려고하면 로컬 변수를 s/def 매크로에 전달하고 매크로를 확장하기 전에 변수를 값으로 해석하지 않기 때문에 함수가 실패하면 함수를 호출하려고합니다.등록 clojure.specs는

(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)) 

내가 원하는 것을 달성 할 수있는 방법이 있습니까? 또는 나는 명백한 무엇인가를 오해하고 있는가? 어떤 도움을 주셔서 감사합니다!

답변

3

이름이 일 때 s/def을 사용하고 싶지 않은 이유가 있습니까? spec의 중요한 측면은 strong/namespaced 이름입니다. 당신의 예제는 특정 의미에서 이름을 제공하지만, 그 맵의 키로서 만 사용됩니다. 나는 그들 모두 s/def을 보내고 싶다. 위의 예에서 몇 가지 오류가 수정되었습니다. 지도 키는 이름 공간이므로 :req-un 대신 s/keys:req을 사용해야합니다.

(s/def ::num-id integer?) 
(s/def :project-spec/id ::num-id) 
(s/def :project-spec/name (s/and string? #(< (count %) 24))) 
(s/def :project-spec/project (s/keys :req [:project-spec/id :project-spec/name])) 

원하는 경우 스펙 맵을 작성할 수 있지만 키/값은 동일합니다.

(s/conform :project-spec/project 
      {:project-spec/id 1, :project-spec/name "123"}) 
;;=> {:project-spec/id 1, :project-spec/name "123"} 
+0

내가 달성하기 위해 노력하고있어 목표는 응용 프로그램의 ClojureScript와 Clojure의 부분에서 모두 사양을 재사용하는 내가 런타임에서에 액세스 할 수 있도록하려면, 그래서 준수 및 검증 할 수 있습니다. 또한이 데이터를 사용할 수있는 기능을 위해 다시 사용하려고합니다. 따라서지도로 사용하는 것이 편리하지만지도에서 전역 레지스트리에 등록하는 데 어려움을 겪고 있습니다. –

+0

또한 네임 스페이스가 아닌'req-un' 키를 넣더라도 네임 스페이스로 키를 제공해야하므로 spec은 키에 해당하는 값의 유효성을 검사 할 수 있습니다. –

+3

@SergeyShvets [이 ​​기사] (http://blog.cognitect.com/blog/2017/3/24/3xeif9bxaom78qyzwssgwz1leuorh4#sharing-specs-across-the-front-and-back-end)를 확인하십시오. CLJ/CLJS를 통해 사양을 재사용하려고 할 때 정확히 무엇을하려는 것인지 설명합니다. 또한, 맵에 스펙을 저장하는 것이 네임 스페이스에서's/def '를 수행하는 것보다 이점이 있는지 확신 할 수 없습니다. –