This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-03-01
Channels
- # aleph (4)
- # arachne (24)
- # beginners (231)
- # boot (4)
- # cider (63)
- # clara (36)
- # cljs-dev (57)
- # clojure (195)
- # clojure-dev (12)
- # clojure-gamedev (2)
- # clojure-greece (1)
- # clojure-italy (10)
- # clojure-poland (4)
- # clojure-spec (36)
- # clojure-uk (65)
- # clojurescript (133)
- # core-async (8)
- # core-logic (2)
- # cursive (18)
- # data-science (3)
- # datomic (58)
- # defnpodcast (3)
- # duct (2)
- # emacs (2)
- # fulcro (27)
- # graphql (3)
- # hoplon (18)
- # jobs (2)
- # jobs-discuss (10)
- # jobs-rus (1)
- # lumo (1)
- # mount (6)
- # nyc (2)
- # off-topic (27)
- # pedestal (13)
- # re-frame (71)
- # reagent (105)
- # reitit (4)
- # ring (2)
- # ring-swagger (1)
- # rum (10)
- # shadow-cljs (172)
- # spacemacs (24)
- # sql (26)
- # tools-deps (1)
- # uncomplicate (4)
- # unrepl (51)
- # vim (3)
- # yada (11)
I must be missing something very simple about composing specs
(s/def ::nums (s/alt :pos pos? :neg neg?))
(s/def ::int int?)
(s/def ::all (s/and ::nums ::int))
(s/valid? ::all 5)
;; => false
(s/explain ::all 5)
;; => val: [:pos 5] fails spec: :myns/int predicate: int?
so the ::nums spec uses s/conform
and changes the value being validated. So ::int
is trying to validate [:pos 5]
and failing.
How do I avoid this though? I just want to chain validations together, each validating the original value I pass in
I feel like I ran into this recently but can't find any evidence of that
I think there's an s/unform
or something like that that could be a workaround
but that seems like it shouldn't be necessary
I know this has been talked about a lot, just don't remember any conclusions
thanks @gfredericks - It seems like for my actual work scenario I can use s/merge
instead of s/and
.
I'm curious what the recommended approach is for the example I pasted though
I googled around for unform, didn't find much
It’s best to start s/and with the pred that conforms to itself, particularly a type predicate like int? that will also generate
You’re probably thinking of the undocumented s/nonconforming wrapper
Still on the fence about that one
However I’d just do (s/and ::int ::nums) here
And s/or is better than s/alt here (although you won’t see any difference in behavior until you combine ::nums with another regex spec
here’s a tricky situation: I have a very large spec to describe my very large config. The config contains values in different nested maps that need to be consistent with each other (some have to co-occur, some refer to each other so IDs need to be consistent etc), so in order to validate the config I have extra predicates on the top-level spec to check for consistency. That was great, until I tried generating a config, and of course it wasn’t valid (because it’s very unlikely to get consistency by chance). So I started writing overwriter functions that would be used via fmap
in the generator in order to re-align the different parts of the randomly generated config. But it does feel a bit like an uphill struggle. Am I missing something?
generating large structures with semantic constraints is (inherently) hard
an alternate approach is to supply a custom generator at the point of use (with stest/check for example) that picks from example configs
by using a generator on a set of enumerated examples
@alexmiller thanks for the insight. I don’t like the idea of giving up the variability that I get from using an actual generator instead of example configs (which I assume you’re implying would he “hand”-written). You’re right, it’s inherently hard… I’ll see if I can refactor a bit to decomplect the constraints between distant parts of the structure, and also see if I can express the ones that cannot be avoided in a more fluent way.
the general approach if you are using custom generators is to first build a generator for a simpler model, then use gen/bind to create a generator that produces the appropriate structure
I’ve done this before, but I think it’s not so applicable in this case, this one has cases where you get a bunch of IDs generated for part of the structure (say metrics
collection), and then in another part (for example filter-metric
) you need to refer to one of the existing metrics, so the overwriter just replaces the generated filter-metric
with one from the IDs in the metrics
collection
you’d think that a flag on one of the metrics (something like :filter?
) would be better… I’m beginning to think the same 🙂
I have a string I want to write a spec for, but it is composed of previously-spec'd string A, followed by a /
, and then previously-spec'd string B. They are GitHub "user/repo"
strings. If I already have a :github/user
spec and a :github/repo
spec, how would I write a spec for the "user/repo"
strings that composes those first two specs?
spec is not great for doing composition of string specs like this - I suspect composing the patterns and creating a spec from that will probably end up better
👋 Hey Alex! OK, thanks. I figured it was either something like that or I was missing something really simple. I'll go down the route you suggest. Thanks!
it’s possible, I just don’t know that you’d be happy with the spec, the generated values, or the conformed values once you were done
I see
@stathissideris generator is "just a function", so you can generate a set of ids upfront, and inject those in sub-generators. it will be verbose and might not be pretty, but sometimes you got to do what you got to do...