2016-07-07 10 views
1

Я пытаюсь написать спецификацию для функции слияния, которая принимает функцию и отображает как входной сигнал и использует функцию для разрешения конфликтов. Однако спецификация, которую я написал для функции, терпит неудачу. Я пытаюсь выяснить, как написать спецификацию для таких функций.Clojure Spec для функции 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}) 

Спецификация ошибки я получаю:

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

В вашей [:args :func] спецификации:

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

Вы хотите сказать, что функция должна принимать в качестве аргументов любое число из карты и вернуть карту. Но функция вы передаете deep-merge-with не соответствует этой спецификации:

(fn [f s] s) 

Эта функция принимает ровно два аргументов, а не произвольное число карт.

+0

'(deep-merge-with (fn [& maps] (последние карты)) {: a 1} {: a 2})' тоже не работает, как мы применяем spec on '(fn [fs ] s) ', чтобы сделать spec, взяв ровно два аргумента. – Paul

+0

@Vijay Вы можете использовать '(spec/cat: m1 map?: M2 map?)' Для спецификации ': args' функции, которая принимает ровно два аргумента карты. –

+0

Большое спасибо, это помогло мне отладить проблему, я глуп, мои входные данные не являются картами, во время процесса глубокого слияния при вызове merge-with func он фактически передает противоречивые значения для функции. так что такая спецификация будет работать '(spec/fdef deep-merge-with: args (spec/cat: func (spec/fspec: args (spec/cat: m1 :: spec/any: m2 :: spec/any) : ret :: spec/any): maps (spec/cat: maps (spec/* :: spec/any))): ret map?) ' – Paul

 Смежные вопросы

  • Нет связанных вопросов^_^