* оператор регулярного выражения в clojure.spec - PullRequest
2 голосов
/ 08 апреля 2019

Согласно Спецификации

* оператор регулярного выражения: проверяет 0 или более предикатов / шаблонов , как это:

(s/def ::seq-of-keywords (s/* keyword?))

;; opts are alternating keywords and booleans
(s/def ::opts (s/* (s/cat :opt keyword? :val boolean?)))
(s/conform ::opts [:silent? false :verbose true])
;;=> [{:opt :silent?, :val false} {:opt :verbose, :val true}]

Но, насколько я понимаю, s/cat проверяет последовательность.

Так почему (s/* (s/cat)) не для проверки последовательности последовательности, каждая из которых соответствует (s/cat).

Что-то вроде этого:

(s/conform ::opts [[:silent? false] [:verbose true]])

Почему этовести себя как s/* flatten ed s/cat?Или Как я могу проверить что-то вроде [[:silent? false] [:verbose true]]?

Ответы [ 2 ]

1 голос
/ 08 апреля 2019

Вы делаете это с помощью coll-of:

(s/conform (s/coll-of ::opts) [[:silent? false] [:verbose true]])
=> [[{:opt :silent?, :val false}] [{:opt :verbose, :val true}]]

Иногда это помогает генерировать данные выборки:

(gen/generate (s/gen ::opts))
=> (:aqfR6b*C/.  false  :?.03/Vu7?  false  :Y17UL0/McsI5h  true)

, которая не соответствует шаблону [[:silent? false] [:verbose true]]

Но этот должен быть, вероятно, ближе к тому, что вы ищете:

(gen/generate (s/gen (s/coll-of (s/tuple keyword? boolean?))))
=> [[:X_o.u?7i/o.dIgTy false]  [:L?*/_WY._:z true]  [:X26:-j/l2q!u-7I false]]
0 голосов
/ 10 апреля 2019

Почему ... s/* выравнивается s/cat?

... потому что регулярное выражение - это структурированная спецификация последовательности flat . Перефразируя Спец-руководство по последовательностям ...

  • Когда операции регулярного выражения объединяются, они описывают одну последовательность.
  • Чтобы указать вложенную последовательность, заключите ее в явный вызов s/spec.

Как мне указать что-то вроде [[:silent? false] [:verbose true]]?

Чтобы указать последовательность пар, каждая из которых является ключевым словом, за которым следует логическое значение:

(s/def ::opts (s/* (s/spec (s/cat :opt keyword? :val boolean?))))

Обратите внимание на s/spec, обертывающий s/cat. Теперь, например, ...

=> (s/conform ::opts [[:silent? false] [:verbose true]])
[{:opt :silent?, :val false} {:opt :verbose, :val true}]

Можно, конечно, как akond , использовать

  • s/tuple вместо s/cat и
  • s/coll-of вместо s/*

без необходимости вставлять s/spec.

...