2016-07-07 29 views
1

Ich versuche, eine Spezifikation für eine Merge-Funktion zu schreiben, die eine Funktion übernimmt und als eine Eingabe abbildet und Funktionen verwendet, um die Konflikte aufzulösen. Die Spezifikation, die ich für die Funktion geschrieben habe, schlägt jedoch fehl. Ich versuche herauszufinden, wie man Spezifikationen für solche Funktionen schreibt.Clojure Spec auf einer Vararg-Funktion

Unten ist das Code-Snippet.

(require '[clojure.spec.test :as stest]) 
(require '[clojure.spec :as spec]) 

(defn deep-merge-with [func & maps] 
    (let [par-func (partial deep-merge-with func)] 
    (if (every? map? maps) 
     (apply merge-with par-func maps) 
     (apply func maps)))) 

(spec/fdef deep-merge-with 
      :args (spec/cat :func (spec/fspec :args (spec/cat :maps (spec/* map?)) 
              :ret map?) 
          :maps (spec/cat :maps (spec/* map?))) 
      :ret map?) 

(stest/instrument `deep-merge-with) 

(deep-merge-with (fn [f s] s) {:a 1} {:a 2}) 

Die Spezifikation Fehler ich bin immer ist:

clojure.lang.ExceptionInfo: Call to #'boot.user/deep-merge-with did not conform to spec: 
    In: [0] val:() fails at: [:args :func] predicate: (apply fn), Wrong number of args (0) passed to: user/eval22001/fn--22002 
           :clojure.spec/args (#function[boot.user/eval22001/fn--22002] {:a 1} {:a 2}) 

Antwort

0

In Ihrem [:args :func] spec:

(spec/fspec :args (spec/cat :maps (spec/* map?)) :ret map?) 

Sie sagen, dass die Funktion als Argumente akzeptieren müssen eine beliebige Anzahl von Karten und geben Sie eine Karte zurück. Aber die Funktion, die Sie deep-merge-with passieren entspricht nicht dieser Spezifikation:

(fn [f s] s) 

Diese Funktion nimmt genau zwei Argumente, nicht eine beliebige Anzahl von Karten.

+0

'(deep-merge-with (fn [& maps] (letzte Karten)) {: a 1} {: a 2})' hat auch nicht funktioniert, wie erzwingen wir spec auf '(fn [fs ] s) 'Spec genau zwei Argumente zu machen. – Paul

+0

@Vijay Sie könnten '(spec/cat: m1 map?: M2 map?)' Für eine ': args'-Spezifikation einer Funktion verwenden, die genau zwei Map-Argumente benötigt. –

+0

Vielen Dank, es hat mir geholfen, das Problem zu debuggen, ich bin dumm, meine Funktion Eingänge sind keine Karten, während der tiefen Merge-Prozess, wenn eine Zusammenführung mit func aufgerufen wird, übergibt es tatsächlich die widersprüchlichen Werte für die Funktion. also wird eine Spezifikation wie diese funktionieren '(spec/fdef deep-merge-with: Argumente (spec/cat: func (spec/fspec: args (spez/cat: m1 :: spec/any: m2 :: spec/any) : ret :: spec/any): Karten (spec/cat: Karten (spec/* :: spec/any))): ret map?) ' – Paul