Fork me on GitHub
#clojure-spec
<
2017-03-03
>
madstap15:03:43

Is this a known bug in spec? I'd expect both to return the same thing, but using s/and with s/keys* doesn't seem to work.

(s/def ::x int?)

  (s/conform (s/cat :a (s/and int? (constantly true))
                    :x (s/keys* :opt-un [::x]))
             [3 :x 3])
  ;=> {:a 2 :x {:x 3}}

  (s/conform (s/cat :a int?
                    :x (s/and (s/keys* :opt-un [::x]) (constantly true)))
             [3 :x 3])
  ;=> :clojure.spec/invalid

moxaj15:03:29

@madstap by wrapping your keys* spec with and, I believe it's no longer a regex spec

(s/conform (s/cat :a int?
                  :x (s/and (s/keys* :opt-un [::x]) (constantly true)))
           [3 [:x 3]])
;=> {:x {:x 3}, :a 3} 

Alex Miller (Clojure team)15:03:48

correct - use s/& instead to add a predicate but keep it as a regex op

Alex Miller (Clojure team)15:03:49

the and spec above would be looking for data like [3 [:x 3]]

bbloom19:03:22

This is on HN right now. I’ve read the intro & it’s pretty awesome: https://www.cl.cam.ac.uk/~sd601/thesis.pdf — of interest to anybody doing static analysis with spec, or just generally interested in both open/extensible and types

jrheard23:03:48

hiya - beginning to add spec to a preexisting project, and i’m running into this situation: i’m trying to spec some “event” maps, which have required keys including :type (eg one of :foo, :bar, :baz) and :data. and the thing is that when :type is :foo, :data is a map that looks like {:a 1 :b 2}; and when :type is :bar, :data is a map that looks like {:c 3 :b 4}; and when :type is :baz, :data is a number like 1234, etc. what do i want in this situation - is this the exact situation where i should reach for a multi-spec?

jrheard23:03:39

i’m beginning to think that having :data be the name for several different categories of thing will be a problem there

jrheard23:03:23

and this codebase is small enough, and there are few enough event types, that i can have :foo events have an :event/thing key, and :bar events have an :event/user-id key, etc

jrheard23:03:32

so i think doing that, and using a multi-spec, is probably the right approach here. rad.