(require '[clojure.spec :as s])
рассмотрит следующие данные:Синтаксических с clojure.spec
(def data {:names [["Anna" :lucky]
["Peter"]
["Jon" :lucky]
["Andre" :lucky]]})
Это хэш-карта с одним ключом: имена, имеющим значение вектора векторов. Внутренние векторы должны содержать строку в качестве первого элемента и необязательно содержать ключевое слово: lucky, как второй элемент.
Предыдущие два предложения должны быть описаны с clojure.spec
- Давайте начнем с элементами в векторе:
(s/def ::item (s/cat :name string? :lucky (s/? #(= :lucky %))))
(s/conform ::item ["Tom"])
;; {:name "Tom"}
(s/conform ::item ["Tom" :lucky])
;; {:name "Tom", :lucky :lucky}
(s/conform ::item ["Tom" :sad])
;; :clojure.spec/invalid
Это работает. Однако, если есть только один вариант. Не будет ли анализируемая результат выглядеть лучше так:
`{:name "Tom", :lucky true}` or `{:name "Tom", :lucky false}`
Можно ли это сделать в clojure.spec?
С этим, можно продолжить:
(s/def ::items (s/coll-of ::item '()))
(s/conform ::items [["Tom" :lucky] ["Tim"]])
[["Tom" :lucky] ["Tim"]]
Однако, похоже, что он проходит тест, но почему пункты не разобран больше?
Edit:Это может быть решена за счет перехода от alpha7 к высвобождению alpha10, где Coll-только из принимает один аргумент
Наконец моя спецификация выглядит, имея ранее описанные предостережений:
(s/def ::my-spec (s/keys req-un [::items]))
Просто сторона примечания - '# (=: lucky%)' лучше spec'ed как '# {: lucky}'. –