Fork me on GitHub
#clojure-spec
<
2017-05-15
>
danielneal09:05:49

I'm trying to take a reagent vector, conform it, make a modification and unform it back.

(s/def :reagent/vector
    (s/cat :element any? :props (s/? map?) :children (s/* any?)))
This conforms fine:
(s/conform :reagent/vector [:div {:a 3} [:div "1207"] [:div "w13"]])
;; => {:element :div, :props {:a 3}, :children [[:div "1207"] [:div "w13"]]}
but unforms back to a lazyseq - is there a spec I can use that will make unform turn it back to a vector?

danielneal09:05:45

I tried prefixing with s/and vector but I think that was wrong

dergutemoritz09:05:32

@danieleneal Wrapping it in (s/and ... (s/conformer identity vec)) should do the trick

dergutemoritz09:05:00

Oh or maybe you have to put it before the s/cat really

dergutemoritz09:05:04

Interesting ...

danielneal09:05:21

yeah (s/and (s/conformer identity vec) ... works, thanks @dergutemoritz

danielneal09:05:40

is that appropriate/idiomatic do you know?

dergutemoritz09:05:16

I guess that's an innocent enough use of s/conformer, yeah ๐Ÿ™‚

dergutemoritz09:05:36

Maybe we should call this kind of use "vegan" as opposed to the "meat grinder" pattern

dergutemoritz09:05:34

"No animals were harmed in this use of s/conformer"

alexmiller14:05:33

the need for regex ops in a vector is a known issue - itโ€™s pretty challenging right now to get conforming, validation, unforming, generation, and describing to work properly together

zane21:05:43

What's the right way to attach a generator to a value produced by s/conformer?

zane22:05:30

Right, but how?

zane22:05:35

Does it need to be attached to a keyword?

zane22:05:40

e.g.

(def keyword-conformer
  (s/with-gen
    (s/conformer
     (fn [x]
       (cond (keyword? x) x
             (string? x) (keyword x)
             :else :clojure.spec/invalid)))
    #(s/gen keyword?)))

zane22:05:43

Should that work? โ˜๏ธ:skin-tone-2:

zane22:05:10

i.e. Should I be able to (gen/sample (s/gen keyword-conformer)) on that?

alexmiller22:05:42

works for me

zane22:05:31

Might be my version of clj, then.

zane22:05:14

I have several other specs like:

(s/def ::example (s/and keyword-conformer #{:some :specific :values}))

zane22:05:40

Of course, calling (gen/sample ::example) fails because it runs out of tries.

zane22:05:36

I've been working around that with

(s/def ::example
  (s/with-gen
    (s/and keyword-conformer
           #{:some :specific :values})
    #(s/gen #{:some :specific :values})))
but that feels gross. Is there a better way?

alexmiller23:05:57

(s/def ::example #{:some :specific :values "some" "specific" " "values"}) would work :)

alexmiller23:05:26

What do you actually need to spec?