Fork me on GitHub
#clojure-spec
<
2019-07-06
>
misha13:07:29

@roklenarcic can you give an example, where/how it limits you?

roklenarcic15:07:01

Let's say you define (s/def ::date-time (s/conformer to-date-time-string from-date-time-string)). This conforming spec will print date time object into a string (or vice versa on unform call). If you define several s/keys specs each containing some fields of this type and then you defined a merged spec with s/merge you will end up with having a situation where after conforming an object only a third of date time properties will be conformed to strings the rest will remain datetime objects and it will fail.

misha18:07:01

This sounds reasonable, although alexmiller stated many times that conformers are not for (this kind of) data transformation.

misha18:07:23

(s/def :foo/s-int (s/conformer #(Integer/valueOf ^String %) str))
(s/def :foo/a :foo/s-int)
(s/def :foo/b :foo/s-int)
(s/def :foo/merge
  (s/merge 
    (s/keys :req [:foo/a])
    (s/keys :req [:foo/b])))

(s/conform :foo/s-int "1") ;; => 1
(s/unform :foo/s-int 1) ;;=> "1"

(s/valid? :foo/merge {:foo/a "1"})  ;;=> false
(s/valid? :foo/merge {:foo/a "1" :foo/b "2"}) ;; => true
(s/conform :foo/merge {:foo/a "1" :foo/b "2"})  ;;=> #:foo{:a 1, :b 2}
(s/unform :foo/merge {:foo/a 1 :foo/b 2}) ;;=> #:foo{:a "1", :b "2"}

roklenarcic15:07:10

If data transformation is not the intent, then what IS the intent of conforming?

misha15:07:43

To tell you how exactly data is valid or invalid. The line is somewhat blurry though.

misha15:07:48

Read up threads linked in SO answer

misha13:07:24

you might be able to use s/and, which "flows" conformed values as part of validation:

(s/conform   (s/and (s/or :k keyword? :i int?) vector?)  1)
=> [:i 1]
(s/valid?  (s/and (s/or :k keyword? :i int?) vector?)  1)
=> true

misha13:07:42

(but intent readability suffers, imo)

Diego Melendez17:07:22

how do I write a s/fdef for a function that does not receive args?

Jakub Holý (HolyJak)17:07:15

I guess leave out args or eg (s/coll any? :count 0)?