Reputation: 8854
In Clojure 1.9.0-alpha13, I can define a spec predicate using spec/and
and integer?
but not and
and number?
, it appears. This is puzzling. It's also puzzling that there is no error when I define the predicate, but only when I try to define a spec using it.
user=> (use '[clojure.spec :as s])
...
nil
user=> (s/def pos-int? (s/and integer? pos?))
user/pos-int?
user=> (s/def ::foo pos-int?)
:user/foo
user=> (s/def pos-num? (s/and number? pos?))
user/pos-num?
user=> (s/def ::bar pos-num?)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: pos-num? ...
Why do I get an error in the second case, but not the first? Is this a feature involving a distinction that I'm unaware of, or a bug?
Note that there is no error if I define ::bar
directly:
user=> (s/def ::bar (s/and number? pos?))
:user/bar
Upvotes: 0
Views: 290
Reputation: 70239
Your code here is incorrect. s/def
should be called with a qualified-keyword to register a spec, not a symbol.
So this:
user=> (s/def pos-int? (s/and integer? pos?))
user/pos-int?
is not doing what you think it is. It is actually registering a function definition (which you typically do via s/fdef
) under the symbol user/pos-int?
.
user=> (s/def ::foo pos-int?)
:user/foo
This works because pos-int?
is an existing function in clojure.core (that is, it's not using your prior definition at all).
This also appears to work but is similarly incorrect:
user=> (s/def pos-num? (s/and number? pos?))
user/pos-num?
This fails:
user=> (s/def ::bar pos-num?)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: pos-num? ...
because pos-num is not an existing predicate.
Presuming you want to register two specs for positive integers and numbers you could do:
(s/def ::pos-int (s/and integer? pos?))
(s/def ::pos-num (s/and number? pos?))
Upvotes: 3
Reputation: 29976
I believe your have discovered an interaction with the pre-defined pos-int?
from clojure.core
. In the source code:
src/clj/clojure/core.clj line 1400
(defn pos-int?
"Return true if x is a positive fixed precision integer"
{:added "1.9"}
[x] (and (int? x)
(pos? x)))
There is no pos-num?
present.
Upvotes: 1