I'm playing with clojure.spec (alpha7) to validate a data structure storing 
information about workout history using the following code:

(ns v.scratch.lift-tracker
  (:require [clojure.spec :as s]))

(defrecord duration [hours minutes seconds])
(defrecord rep_scheme [weight repetitions])

(s/def ::day (s/and int? pos? #(< % 32)))
(s/def ::month (s/and int? pos? #(< % 13)))
(s/def ::year (s/and int? pos?))
(s/def ::date (s/tuple ::year ::month ::day))
(s/def ::hours int?)
(s/def ::minutes int?)
(s/def ::seconds int?)
(s/def ::weight number?)
(s/def ::repetitions (s/and int? pos?))
(s/def ::exercise-id keyword?)
(s/def ::workout (s/map-of ::exercise-id (s/or :duration (s/coll-of
                                                          (s/keys :req-un 
[::hours ::minutes ::seconds])
                                                          [])
                                               :rep_scheme (s/coll-of
                                                            (s/keys :req-un 
[::weight ::repetitions])
                                                            []))))
(s/def ::history (s/map-of ::date ::workout))

The problem is that when using s/explain on an invalid input where the 
error is near the leaves, the error message points at the root of the data 
structure, which is not as useful.

(s/explain
 ::history
 {[2015 6 31] {:chinups [(->rep_scheme 0 13)
                         (->rep_scheme :x 13)]
               :l-sit [(->duration 0 0 10)]}
  [2016 6 31] {:chinups [(->rep_scheme 0 13)
                         (->rep_scheme 0 14)]
               :l-sit [(->duration 0 0 10)]}})

val: {[2015 6 31] {:chinups [#v.scratch.lift_tracker.rep_scheme{:weight 0, 
:repetitions 13} #v.scratch.lift_tracker.rep_scheme{:weight :x, 
:repetitions 13}], :l-sit [#v.scratch.lift_tracker.duration{:hours 0, 
:minutes 0, :seconds 10}]}, [2016 6 31] {:chinups 
[#v.scratch.lift_tracker.rep_scheme{:weight 0, :repetitions 13} 
#v.scratch.lift_tracker.rep_scheme{:weight 0, :repetitions 14}], :l-sit 
[#v.scratch.lift_tracker.duration{:hours 0, :minutes 0, :seconds 10}]}} 
fails spec: :v.scratch.lift-tracker/history predicate: (coll-checker (tuple 
:v.scratch.lift-tracker/date :v.scratch.lift-tracker/workout))

Is there a built in way to automatically recurse the sub-components to 
identify the problematic scope?

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to