Число? не может быть использован в спецификации

В 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

2 ответа

Решение

Ваш код здесь неверный. 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?))

Я считаю, что вы обнаружили взаимодействие с предопределенным 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? подарок.

Другие вопросы по тегам