Как вы используете fdef с картами в параметрах?

Я пытаюсь заставить fdef успешно пройти проверку с набором карт в качестве параметра. Я получаю следующее:

(defn func
  [foo bar])
(def t [{:a "hi ":b "jimbob"} {:a "hi" :b "johnboy"}])
(spec/def ::a string?)
(spec/def ::b string?)
(spec/def ::c string?)
(spec/def ::d string?)
(spec/fdef func :args
           (spec/cat :foo string?
                     :bar (spec/+ (spec/keys
                                    :req-un [::a ::b]
                                    :opt-un [::c ::d]))))
(stest/instrument)
(func "hello" t)
=> #'user/func
=> #'user/t
=> :user/a
=> :user/b
=> :user/c
=> :user/d
=> user/func
=> [user/func]
ExceptionInfo Call to #'user/func did not conform to spec:
In: [1] val: [{:a "hi ", :b "jimbob"} {:a "hi", :b "johnboy"}] fails at: [:args :bar] predicate: map?
  clojure.core/ex-info (core.clj:4739)

Очевидно, мне не хватает того, как связать аргументы с их спецификацией; это работает:

(spec/explain string? "hello")
Success!
=> nil

Как и это

(spec/explain (spec/+ (spec/keys
                        :req-un [::a ::b]
                        :opt-un [::c ::d]))
                      [{:a "hi ":b "jimbob"} {:a "hi" :b "johnboy"}])
Success!
=> nil

Любая помощь высоко ценится!


person dardenfall    schedule 30.03.2018    source источник


Ответы (1)


Изменение «spec/+» на «spec/coll-of» устраняет проблему:

(defn func
  [foo bar])
(def t [{:a "hi ":b "jimbob"} {:a "hi" :b "johnboy"}])
(spec/def ::a string?)
(spec/def ::b string?)
(spec/def ::c string?)
(spec/def ::d string?)
(spec/fdef func :args
           (spec/cat :foo string?
                     :bar (spec/coll-of (spec/keys
                                    :req-un [::a ::b]
                                    :opt-un [::c ::d]))))
(stest/instrument)
(func "hello" t)
=> #'user/func
=> #'user/t
=> :user/a
=> :user/b
=> :user/c
=> :user/d
=> user/func
=> [user/func]
=> nil
person dardenfall    schedule 31.03.2018