在Clojure 1.9.0-alpha13中,我可以使用spec/and
和integer?
而不是and
和number?
来定义规范谓词。这令人费解。令我费解的是,在定义谓词时没有错误,但只有在我尝试使用它定义规范时才会出现错误。
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? ...
为什么我在第二种情况下会出错,但不是第一种情况?这是一个涉及我不知道的区别或错误的特征吗?
请注意,如果我直接定义::bar
,则没有错误:
user=> (s/def ::bar (s/and number? pos?))
:user/bar
答案 0 :(得分:2)
此处的代码不正确。应使用qualified-keyword调用s/def
来注册规范,而不是符号。
所以这个:
user=> (s/def pos-int? (s/and integer? pos?))
user/pos-int?
没有做你想象的那样。它实际上是在符号s/fdef
下注册一个函数定义(通常通过user/pos-int?
进行)。
user=> (s/def ::foo pos-int?)
:user/foo
这是有效的,因为pos-int?
是clojure.core中的现有函数(也就是说,它根本没有使用您之前的定义)。
这似乎也有效,但同样不正确:
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? ...
因为pos-num 不是现有的谓词。
假设您要为正整数和数字注册两个规格:
(s/def ::pos-int (s/and integer? pos?))
(s/def ::pos-num (s/and number? pos?))
答案 1 :(得分:1)
我相信您发现了与来自pos-int?
的预定义clojure.core
的互动。在源代码中:
src / clj / clojure / core.clj第1400行
(defn pos-int?
"Return true if x is a positive fixed precision integer"
{:added "1.9"}
[x] (and (int? x)
(pos? x)))
没有pos-num?
出现。