Skip to content

Instantly share code, notes, and snippets.

@danielneal
Last active October 26, 2017 11:00
Show Gist options
  • Save danielneal/43c8dc5d0d3a1d4cadd55d965f5076c1 to your computer and use it in GitHub Desktop.
Save danielneal/43c8dc5d0d3a1d4cadd55d965f5076c1 to your computer and use it in GitHub Desktop.
How to get the args of a fn spec?
;; How do I get the args of a fn spec?
;; (I'd like to do some kind of dumb intellisense using specs in the registry)
;; For example, with a function a
(defn a [m]
(get m :foo))
(s/fdef a
:args (s/cat :m map?)
:ret int?)
;; Get it's spec out of the registry
(def a-spec
(get (s/registry) (symbol (str *ns*) "a")))
;; parse the spec
(s/def
::fn-spec
(s/cat :fspec- #{'clojure.spec.alpha/fspec}
:args- #{:args}
:args (s/spec (s/cat :cat- #{'clojure.spec.alpha/cat}
:args (s/* (s/cat :arg keyword? :spec any?))))
:ret- #{:ret}
:ret any?
:fn- #{:fn}
:fn any?))
(get-in (s/conform ::fn-spec (s/form a-spec)) [:args :args])
;; gives this
[{:arg :m, :spec clojure.core/map?}]
;; but that :spec is a quoted list - to turn it back into a spec, I could
;; possibly do eval
(def arg-spec (s/spec (eval (-> (s/conform ::fn-spec (s/form a-spec))
:args
:args
first
:spec))))
;; => #object[clojure.spec.alpha$spec_impl$reify__739 0x69ada674 "clojure.spec.alpha$spec_impl$reify__739@69ada674"]
(s/valid? arg-spec {:a 1}) ;=> true
;;; but maybe there is a better way?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment