2016-07-07 5 views
1

関数を使用して入力としてマップし、関数を使用して競合を解決するマージ関数の仕様を記述しようとしています。しかし、関数のために書いた仕様は失敗します。私はそのような関数の仕様書を書く方法を理解しようとしています。Clojure仕様のvararg関数

以下はコードスニペットです。

(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}) 

私は取得していますスペックエラーがある:あなたの[:args :func]スペックで

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}) 

答えて

0

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

あなたは関数は引数として受け入れなければならないということ、任意の数のを言っていますマップを作成し、マップを返します。しかし、あなたはdeep-merge-withに渡す機能は、その仕様に準拠していません。

(fn [f s] s) 

この関数は正確にの引数ではなく、マップの任意の数をとります。

+0

'(deep-merge-with(fn [&maps](last maps)){:a 1} {:a 2})'は動作しませんでした。 'fn [fs ] s) 'を実行して、specにちょうど2つの引数をとります。 – Paul

+0

@Vijay厳密に2つのマップ引数を取る関数の ':args'仕様に'(spec/cat:m1 map?:m2 map?) 'を使うことができます。 –

+0

マージ・オン機能が呼び出されたときのディープ・マージ・プロセス中に、機能入力がマップではなく、機能の矛盾する値を実際に渡してしまったので、問題をデバッグするのに役立ちました。 (spec/cat:m1 :: spec/any:m2 :: spec/any)このような仕様では、 '/ fdef deep-merge-with:args(spec/cat:func(spec/fspec:args :ret :: spec/any):maps(spec/cat:maps(spec/* :: spec/any))):ret map?) ' – Paul