2016-06-30 19 views
8

Podążam za numerem clojure.spec guide. Rozumiem, że można zadeklarować wymagane i opcjonalne atrybuty podczas używania clojure.spec/keys.Niedozwolone klucze w clojure.spec

Nie rozumiem, co rozumie się przez opcjonalne. Dla mnie: opt nic nie robi.

(s/valid? (s/keys :req [:my/a]) {:my/a 1 :my/b 2}) ;=> true 

(s/valid? (s/keys :req [:my/a] :opt []) {:my/a 1 :my/b 2}) ;=> true 

Przewodnik obiecuje wyjaśnić to do mnie: „Zobaczymy później, gdzie opcjonalne atrybuty mogą być użyteczne”, ale nie udało mi się znaleźć wyjaśnienie. Czy mogę zadeklarować niedozwolone klucze? Lub w jakiś sposób zadeklaruj zestaw poprawnych kluczy, aby były równe kluczom w: req i: opt?

Odpowiedz

8

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"} 
+0

"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

+0

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

-3

Chodzi o kluczach opcjonalnych jest że wartość zostanie zatwierdzona, jeśli pojawią się na mapie

+1

To nieprawda. Wartość zostanie zweryfikowana niezależnie. –

+0

Jeśli klucz nie jest wymagany ani opcjonalny, wartość nie zostanie w ogóle zatwierdzona. Nie miałem na myśli, że dla wymaganych kluczy wartość nie została zatwierdzona. – DanLebrero

+1

"Ponadto wszystkie wartości * wszystkich * kluczy o nazwach zastrzeżonych zostaną zwalidowane (i ewentualnie zniszczone) przez wszelkie zarejestrowane specyfikacje." (Docstr. Of 's/keys') –

Powiązane problemy