I just spend a solid 2 hours trying to figure out how to make a schema -> select work in Spec1. Started diving deeper into the Spec2 code to land on this https://github.com/clojure/spec-alpha2/blob/495e5ac3238be002b4de72d1c48479f6bec06bb3/src/main/clojure/clojure/alpha/spec/impl.clj#L421. I think this makes sense. I'm curious if there is more reasoning behind it since it seems like there isn't a technical reason as to why you can't have a select within a schema.
I guess it's more of a fundamental thing -- a schema is always a set of optional attributes. If attributes become required, it cannot be a schema.
yes, that
I'm working on generators for a spec like
(spec/keys :req-un [::interval/start
::interval/end])
but I want to create linkage between the start/end dates.
I've written a generator `
(defn sqlinterval-generator
to give me the interval boundaries that I want,
but what is the best way to poke them in to the overal keys
structure ?
In the past I've used a bind
and fmap
to overwrite the interval boundaries
AFTER the default generator has given me random ones;
seems a bit non-intentional though; is there a better way?go the other way
I guess you kind of are
I don't think what you're doing is bad necessarily
and it might be the easiest way in this situation
so I have this to daisy-chain the generators
(defn generator-decorate-sqlinterval
"overwrites the gen-in values with values from the interval generator"
[gen-in start-key end-key interval-generator]
(test.gen/bind gen-in
(fn [o] (test.gen/fmap
(fn [[start end]] (assoc o start-key start
end-key end))
interval-generator))))
I guess I'm asking if there is something like (test.gen/tuple
but that will give me a map instead of a vector
nah that wouldn't be any easier would it?
I'll keep hacking away at it then
thanks
Does clojure.spec.alpha support defining a spec for a map where keys are not known in advance, but a spec exists for their values?
@waffletower For qualified keys, yes, if I'm understanding you correctly. Not for unqualified keys.
user=> (require '[clojure.spec.alpha :as s])
nil
user=> (s/def :my/key int?)
:my/key
user=> (s/def ::bag (s/keys))
:user/bag
user=> (s/valid? ::bag {})
true
user=> (s/valid? ::bag {:my/key "a"})
false
user=> (s/valid? ::bag {:my/key 1})
true
user=>
Spec checks any (qualified) keys' values against existing specs, even if s/keys
doesn't list them. But if you generate/exercise ::bag
, you will only get empty maps.
Thanks Sean, I need something like a wildcard key, such that every key in a map would validate against a specific spec.
{:unknown 1
:mystery 4
:unspecified 7} etc.
And somehow link any key to be validated against (s/def ::wildcard-key int?)
(s/map-of keyword? ::wildcard-key)
(instead of s/keys
)
let me test that out, thanks
(s/def ::wildcard-key int?)
(s/valid?
(s/map-of keyword? ::wildcard-key)
{:unknown 1
:mystery 4
:unspecified 7})
true
nice, many thanks!