2017-04-13 1 views
1

Lets an der in der Clojure Spec gegebenen Beispiel aussehen Guide für clojure.spec/mergeGenerator für die Vereinigung von zwei Sätzen von Schlüsseln für benannte Argumente mit Clojure Spec

(require '[clojure.spec  :as spec] 
     '[clojure.spec.gen :as gen]) 

(spec/def :animal/kind string?) 
(spec/def :animal/says string?) 
(spec/def :animal/common (spec/keys :req [:animal/kind :animal/says])) 
(spec/def :dog/tail? boolean?) 
(spec/def :dog/breed string?) 
(spec/def :animal/dog (spec/merge :animal/common 
            (spec/keys :req [:dog/tail? :dog/breed]))) 

Von diesem spec wir beide Daten erzeugen kann und wiederum validieren :

(gen/generate (spec/gen :animal/dog)) 
=> {:animal/kind "bB", :animal/says "z9C0T465Q8OPXn5dUB8Wqk8K5Jnn", 
    :dog/tail? false, :dog/breed "B2MLQnj"} 

(spec/valid? :animal/dog 
      {:animal/kind "bB", :animal/says "z9C0T465Q8OPXn5dUB8Wqk8K5Jnn", 
       :dog/tail? false, :dog/breed "B2MLQnj"}) 
=> true 

Aber wenn wir etwas die Spezifikation so zu modifizieren, 0, dass es für eine Folge von benannten Argumente anstelle einer Karte, wie

(spec/def :animal/common (spec/keys* :req [:animal/kind :animal/says])) 
(spec/def :animal/dog (spec/merge :animal/common 
            (spec/keys* :req [:dog/tail? :dog/breed]))) 
war

, können wir noch Daten gegen die Spezifikation validieren:

(spec/valid? :animal/dog 
      '(:animal/kind "dog" 
       :animal/says "woof" 
       :dog/tail? true 
       :dog/breed "retriever")) 
=> true 

Aber wir haben die Fähigkeit verlieren, um Daten zu generieren:

(gen/generate (spec/gen :animal/dog)) 

; 1. Unhandled clojure.lang.ExceptionInfo 
; Couldn't satisfy such-that predicate after 100 tries. 

Ist das ein Fehler auf meiner Seite, wird ein Fehler Implementierung in spec oder einfach so funktioniert clojure.spec/merge? Können wir das umgehen, indem wir einen Generator anbauen?

Antwort

1

Wenn wir uns die Implementierung von spec/merge ansehen, scheint es, dass dort ein spezieller Fall zum Generieren von Maps vorhanden ist, aber nicht zum Erzeugen von Sequenzen von Schlüssel/Wert-Paaren. Ich nehme an, das liegt daran, dass es immer noch Alpha ist und noch nicht einmal API stabil, geschweige denn vollständig implementiert. Die Lieferung Ihres eigenen Generators scheint jedoch den Trick zu leisten. Zum Beispiel:

(gen/generate (spec/gen :animal/dog {:animal/dog #(clojure.test.check.generators/return '(:animal/kind "2qAW61r3030B", :animal/says "7k", :dog/tail? true, :dog/breed "00Y8C9T25cRrSQsnjOn26a"))})) 
Verwandte Themen