Fork me on GitHub
#clojure-spec
<
2018-12-13
>
noprompt05:12:35

There’s also the greek letter beta. troll

noprompt05:12:55

Why should beta be reserved only for use-at-your-own-risk software I ask? 😄

jumar10:12:13

Let's say I have following config spec:

(s/def ::my-config-spec
  (s/keys :req-un [::host
                   ::port
                   ]))

(s/explain-data ::my-config-spec {:host ""})
;; => #:clojure.spec.alpha{:problems (
;;    {:path [], :pred (clojure.core/fn [%] (clojure.core/contains? % :port)),
;;     :val {:host ""}, :via [:cacsremoteservice.config/my-config-spec], :in []}), :spec :cacsremoteservice.config/my-config-spec, :value {:host ""}}
I used explain-data and returned :path key to indicate which keys are in the config are invalid/missing. What I didn't realize is that when the key is missing then the path is empty (instead of pointing to the particular key). Is there a nice way how to get the name of a missing required key?

seancorfield13:12:22

Not nice but you can pattern match :pred with destructuring since it has that particular shape and extract the missing field name from the contains? call.

jumar13:12:22

Thanks for the idea! I'm sure there's a better way but here's my quick solution:

(defn extract-key [spec-problem]
  (let [[_fn _args [_contains _map req-key]] (:pred spec-problem)]
    req-key))
  
(let [ed (s/explain-data ::my-config-spec {:host ""})]
  (->> ed :clojure.spec.alpha/problems
       (map extract-key)))

seancorfield13:12:01

(And it might change in a future version of spec)