Fork me on GitHub
#clojure-spec
<
2023-07-05
>
MegaMatt20:07:49

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.

MegaMatt20:07:41

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}

MegaMatt20:07:18

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.

seancorfield20:07:01

s/and is conforming, passing the conformed value into the second and subsequent specs.

seancorfield20:07:55

I think if you wrap each s/or in s/nonconforming that will produce what you want.

MegaMatt20:07:03

Update:point_up:: s/nonconforming solved my issue.

1