Symbols and Vars for specs?

59 views
Skip to first unread message

Didier

unread,
Dec 11, 2017, 8:01:20 PM12/11/17
to Clojure
s/def docs says: "Given a namespace-qualified keyword or resolvable symbol ..."

But I'm unable to s/def a spec using a resolvable symbol:

(def foo 123)
(s/def foo int?)
(s/get-spec foo) => nil
(s/get-spec 'foo) => nil
(s/get-spec #'
foo) => #object[clojure.spec.alpha$spec_impl$reify__797 0x7215d8f3 "clojure.spec.alpha$spec_impl$reify__797@7215d8f3"]

So it works with the var, but not the symbol. Also, doing (s/def 'foo int?) fails with an assertion error.

Is it true that specs can be registered with the key being a namespace-qualified keyword, a resolvable symbol or a Var? Or is the doc misleading?

Alex Miller

unread,
Dec 11, 2017, 10:08:42 PM12/11/17
to Clojure


On Monday, December 11, 2017 at 7:01:20 PM UTC-6, Didier wrote:
s/def docs says: "Given a namespace-qualified keyword or resolvable symbol ..."

Symbols are used to register function specs (with the same qualified symbol as the var it's stored with).


But I'm unable to s/def a spec using a resolvable symbol:

(def foo 123)
(s/def foo int?)

This actually will work
 

(s/get-spec foo) => nil

get-spec is actually a function and will receive it's arguments evaluated. So here you are actually doing the same as `(s/get-spec 123)`. Instead, quote and qualify the symbol:

(s/get-spec 'user/foo)

or use syntax quote to take advantage of the fact that syntax quote resolves symbols automatically:

(s/get-spec `foo)
 

(s/get-spec 'foo) => nil

Needs to be qualified as above
 
(s/get-spec #'foo) => #object[clojure.spec.alpha$spec_impl$reify__797 0x7215d8f3 "clojure.spec.alpha$spec_impl$reify__797@7215d8f3"]


There is actually some helper code right now in s/get-spec that also knows how to extract the symbol from the var name (noted in the docstring) - this is useful in some of the stest functions.
 
So it works with the var, but not the symbol. Also, doing (s/def 'foo int?) fails with an assertion error.

Is it true that specs can be registered with the key being a namespace-qualified keyword, a resolvable symbol or a Var? Or is the doc misleading?

Again, I think the key here though is that while this will work, it's not the expected way to use it. You can't declare a spec for a non-function var created via def. Or rather you can, but spec will ignore it in instrument and fail on check.

Where symbol-keyed specs is intended to be used is with functions:

(defn foo [x] (+ x 123))
(s/fdef foo :args int? :ret int?)
(s/form (s/get-spec `foo))  
;;=> (clojure.spec.alpha/fspec :args clojure.core/int? :ret clojure.core/int? :fn nil)

;; also accepts key lookups for the function spec parts:
(s/form (:args (s/get-spec `foo)))
;;=> clojure.core/int?


Reply all
Reply to author
Forward
0 new messages