0

spec/and在 Clojure 1.9.0-alpha13 中,我可以使用andinteger?但不是andand来定义规范谓词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
4

2 回答 2

3

您这里的代码不正确。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?))
于 2016-10-27T22:29:46.803 回答
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?礼物。

于 2016-10-27T19:12:14.700 回答