数?不能在规范

时间:2016-10-27 18:54:24

标签: clojure clojure.spec

在Clojure 1.9.0-alpha13中,我可以使用spec/andinteger?而不是andnumber?来定义规范谓词。这令人费解。令我费解的是,在定义谓词时没有错误,但只有在我尝试使用它定义规范时才会出现错误。

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

2 个答案:

答案 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?出现。