Как принимать только заказанные коллекции в спецификации - PullRequest
0 голосов
/ 13 декабря 2018

Как мне создать спецификацию, которая принимает только последовательные (т.е. сохраняющие порядок) коллекции?

Например

cljs.user=> (s/def ::path (s/+ number?))                                                                                                                                                                                 
:cljs.user/path
cljs.user=> (s/explain ::path [])                                                                                                                                                                                                                           
val: () fails spec: :cljs.user/path predicate: number?,  Insufficient input
:cljs.spec.alpha/spec  :cljs.user/path
:cljs.spec.alpha/value  [] 
cljs.user=> (s/explain ::path [1 2 3])                                                                                                                                                                                                                      
Success!

Это, как и ожидалось, но в то же время, обратите вниманиев порядке

cljs.user=> #{1 2 3}
#{1 3 2}
cljs.user=> (s/explain ::path #{1 2 3})                                                                                                                                                                                                                     
Success!

И это не имеет никакого смысла.Итак, вторичный вопрос:

Почему относящиеся к последовательности выражения (cat, *, +,?) В спецификации допускают коллекции, нарушающие последовательность?

UPD Я перепутал последовательное / упорядоченное различие вОригинальный вопрос.Уточненная терминология.

Ответы [ 2 ]

0 голосов
/ 13 декабря 2018

Спецификации для последовательностей (спецификации регулярных выражений) не должны соответствовать упорядоченным, то есть последовательных коллекций.Эта ошибка была исправлена ​​в текущих версиях спецификации, см. CLJ-2183 .

В Clojure 1.10.0-RC5 результаты ожидаемые:

(s/conform ::path [1 2 3])   ; => [1 2 3]
(s/conform ::path #{1 2 3})  ; => :clojure.spec.alpha/invalid

(s/explain ::path #{1 2 3})
;; #{1 3 2} - failed: (or (nil? %) (sequential? %)) spec: :user/path

В последней строке видно, что спецификации регулярных выражений теперь соответствуют только значениям sequential?.

0 голосов
/ 13 декабря 2018

Как создать спецификацию, которая принимает только коллекции, сохраняющие порядок?

Есть функция предиката clojure.core sorted?, которая будет возвращать true для коллекций, которые реализуют Sorted.

(sorted? (sorted-map))
=> true

Он не возвращает true для коллекций с содержимым, которые отсортированы, но не реализуют Sorted:

(sorted? [1 2 3])
=> false

Вы можете использовать произвольные функции предикатов вspecs, чтобы вы могли определить функцию, которая возвращает true для коллекций с отсортированным содержимым:

(defn ordered? [coll]
  (or (empty? coll) (apply <= coll)))

(ordered? [1 2 3])
=> true

Затем вы можете использовать s/and, чтобы объединить этот предикат с вашей спецификацией регулярного выражения:

(s/def ::path (s/and (s/+ number?)
                     ordered?))

(s/explain ::path [1 2 3])
Success!
=> nil

(s/explain ::path #{1 2 3})
val: [1 3 2] fails spec: :playground.so/path predicate: ordered?
=> nil
...