To jest bardzo dobre pytanie, a clojure.spec API daje (przyznaną, krótki i niezadowalające) Odpowiedź:
The keys opt służyć jako dokumentacja i mogą być wykorzystywane przez generator.
Nie sądzę, że można unieważnić mapę, jeśli zawiera ona dodatkowe (to znaczy, że masz na myśli "zakazany", jak sądzę) klucz, używając tej metody. Jednakże, można użyć tej specyfikacji, aby upewnić :: zły klucz nie jest obecna:
(s/def ::m (s/and (s/keys :req [::a]) #(not (contains? % ::bad-key))))
(s/valid? ::m {::a "required!"}) ; => true
(s/valid? ::m {::a "required!" ::b "optional!"}) ; => true
(s/valid? ::m {::a "required!" ::bad-key "no good!"}) ; => false
Można ograniczyć liczbę klawiszy, aby dokładnie zestaw chcesz przy użyciu tej specyfikacji:
(s/def ::r (s/and (s/keys :req [::reqd1 ::reqd2]) #(= (count %) 2)))
(s/valid? ::r {::reqd1 "abc" ::reqd2 "xyz"}) ; => true
(s/valid? ::r {::reqd1 "abc" ::reqd2 "xyz" ::extra 123}) ; => false
Mimo to najlepszym sposobem na poradzenie sobie z tą IMO byłoby po prostu zignorowanie tego, że istnieje kluczowy prezent, którego nie obchodzi.
Mamy nadzieję, że wraz ze specyfikacją, te ładne rzeczy zostaną dodane. A może już tam są (szybko się zmienia) i po prostu o tym nie wiem. Jest to bardzo nowa koncepcja w clojure, więc większość z nas musi się wiele nauczyć.
AKTUALIZACJA - grudzień 2016 Po prostu chciałem wrócić do tego 6 miesięcy od napisania. Wygląda na to, że mój pierwszy komentarz na temat ignorowania kluczy, których nie obchodzi, jest preferowany. W rzeczywistości, na konferencji clojure/conj, w której uczestniczyłem dwa tygodnie temu, przemówienie Richa odnosiło się do koncepcji wersjonowania na wszystkich poziomach oprogramowania, od poziomu funkcji do poziomu aplikacji. Nawet konkretnie wspomina o tym, że nie wolno używać kluczy w rozmowie, którą można znaleźć pod adresem on youtube. Mówi, że został celowo zaprojektowany, aby można było określić tylko wymagane klucze. Odrzucanie kluczy naprawdę nie służy żadnemu celowi i należy to robić ostrożnie.
Odnośnie :opt
kluczy, myślę, że oryginalna odpowiedź nadal wstaje bardzo dobrze - to dokumentacja, i praktycznie, pozwala te ewentualnie określone klawisze mają być generowane:
(s/def ::name #{"Bob" "Josh" "Mary" "Susan"})
(s/def ::height-inches (s/int-in 48 90))
(s/def ::person (s/keys :req-un [::name] :opt-un [::height-inches]))
(map first (s/exercise ::person))
; some generated data have :height-inches, some do not
({:name "Susan"}
{:name "Mary", :height-inches 48}
{:name "Bob", :height-inches 49}
{:name "Josh"}
"Odrzucanie kluczy naprawdę nie służy żadnemu celowi i należy to robić ostrożnie." Hmm. Będę musiał obejrzeć rozmowę, aby usłyszeć to w kontekście, ale co, powiedzmy, sprawdzając, czy pole hasła nie wycieka z funkcji? Chyba chodzi o to, że naprawdę nie możesz zagwarantować, że nie wyciekniesz go w jakiś inny sposób poza wyraźnym kluczem, ale wydaje się nieco zawyżone stwierdzenie, że sprawdzanie tego, co oczywiste, nie ma dobrego celu, nieprawdaż? – neverfox
Więc wysłuchałem przemówienia. Widzę, że specyfikacja dotyczy tego, co możesz, a nie tego, czego nie możesz zrobić.Ale nie powiedział dokładnie, że ignorowanie tego było preferowanym sposobem. Powiedział, że był to jeden z dwóch preferowanych sposobów, drugi to "mieć politykę". Jeśli dobrze to rozumiem, mogę zrobić kilka rzeczy, aby nie blokować wzrostu: 1) zdefiniuj osobno nazwaną specyfikację z "po prostu zignoruj", która uniemożliwiła użycie klucza, używając metody, którą pokazujesz, której mogę teraz użyć, może zachować używać na zawsze lub upuszczać później, 2) pisać niezależne warcaby. Właściwie zwrócił się również do mojej sprawy: może powinieneś użyć klawiszy wyboru. – neverfox