Wondering why this code produces the prn statements that it does.
(let [shape {:path1 true :path2 {:nested true}}
path-exists? (fn [p o]
(let [p (map keyword (str/split p #"\."))
missing? (= :missing (get-in o p :missing))]
(prn o)
#_(not missing?)
true))]
(s/def ::something (s/and (s/or :path1-exists (partial path-exists? "path1"))
(s/or :path2-exists (partial path-exists? "path2.nested"))
(s/or :path3-exists (partial path-exists? "path2.nested2"))))
(s/valid? ::something {:path1 :here :path2 {:nested :here :nested2 :blah}}))
Res:
{:path1 :here, :path2 {:nested :here, :nested2 :blah}}
[:path1-exists {:path1 :here, :path2 {:nested :here, :nested2 :blah}}]
[:path2-exists [:path1-exists {:path1 :here, :path2 {:nested :here, :nested2 :blah}}]]
I’ll post the why i’m doing this in a thread in case others can suggest a better approach.I’m making a macro which takes a list of dot delimited strings and makes a spec which ensures the shape of the data
eg. (defshape ["a.b.c", "a.d"])
would ensure you have something like
{:a {:b {:c "test"}} :d true}
and sure, just s/and would work but the errors are not helpful to the developer thus i wanted s/or so that i can have a keyword that indicates the problem.
s/and is conforming, passing the conformed value into the second and subsequent specs.
I think if you wrap each s/or in s/nonconforming that will produce what you want.
thank you.
Update:point_up:: s/nonconforming solved my issue.