Как создать спецификацию, в которой все ключи являются необязательными, но должен присутствовать хотя бы один из указанных ключей? - PullRequest
0 голосов
/ 09 июля 2019

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

(s/def ::my-spec (s/and (help-plz??)(s/keys :opt-un [::a ::b]))) 
(s/valid? ::my-spec {} => false
(s/valid? ::my-spec {:a 1}) => true 
(s/valid? ::my-spec {:b 1}) => true 
(s/valid? ::my-spec {:a 1 :b 1}) => true 
(s/valid? ::my-spec {:A1 :B 1}) => true

1 Ответ

5 голосов
/ 09 июля 2019

С текущей альфа-спецификацией, чтобы использовать один и тот же набор ключей как для спецификации keys, так и для проверки, по крайней мере, одного существующего, вам необходимо использовать макрос.(Предстоящая альфа-версия спецификации 2 решает эту проблему, предоставляя больше управляемых данными API для создания спецификаций.)

Вот краткий набросок для вашего конкретного примера:

(defmacro one-or-more-keys [ks]
  (let [keyset (set (map (comp keyword name) ks))]
    `(s/and (s/keys :opt-un ~ks)
            #(some ~keyset (keys %)))))

(s/def ::my-spec (one-or-more-keys [::foo ::bar]))

(s/conform ::my-spec {:bar nil})
=> {:bar nil}
(s/conform ::my-spec {:baz nil})
=> :clojure.spec.alpha/invalid

В качестве альтернативы, вы можете просто определитьдважды наберите ключ и используйте аналогичный предикат с s/and.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...