简体   繁体   中英

Clojure Spec on a vararg function

I am trying to write a spec for a merge function which takes a function and maps as an input and uses function to resolve the conflicts. However the spec i wrote for the function fails. I am trying to figure out how to write spec for such functions.

Below is the 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})

The spec error i am getting is:

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

In your [:args :func] spec:

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

You're saying that the function must accept as arguments any number of maps and return a map. But the function you pass to deep-merge-with does not conform to that spec:

(fn [f s] s)

This function takes exactly two arguments, not an arbitrary number of maps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM