Fork me on GitHub

is there a way in spec to say ::x is a vector of numbers ::y is a vector of numbers ::s is a string and the three have the same length (thisxis regarding to an s/keys)


this is what I have so far:

(s/def ::text-x (s/coll-of number? :kind vector?))
(s/def ::text-y (s/coll-of number? :kind vector?))
(s/def ::text-str string?)
but it's not clear to me how to specify the three have the same length


@qqq Are you using them in a context together? Sounds like you could s/and a length check on top of whatever structure uses all three?



(s/def ::text-x (s/coll-of number? :kind vector?))
(s/def ::text-y (s/coll-of number? :kind vector?))
(s/def ::text-str string?)
(s/def ::svg-text (s/keys :req [::text-x ::text-y ::text-str ]))

is what I have so far


You are recommending (s/and (s/keys ...1) ...2) ?


in ...2 , how do I access the text-x, text-y, text-str fields ?


@qqq something like this?

(defn- vals-same-length?
  (->> (vals m)
       (map count)
       (apply =)))
(s/def ::svg-text-same-length (s/and (s/keys :req [::text-x ::text-y ::text-str ])

(s/valid? ::svg-text-same-length {::text-x   [1 2 3]
                                  ::text-y   [10 20 30]
                                  ::text-str "abc"})
(There might be more straightforward implementation of vals-same-length?)


@jumar: I did not realize I can just pass in an arbitrary clojure function.


This is very useful, thanks!


(sorry, was distracted by the amazing availability of early 80's German electronica on iTunes these days... yes, @qqq what @jumar said... when you use s/and you can have any predicate and it has access to the entire form being processed, so you could access just ::text-x, ::text-y, ::text-str if you wanted, or vals to get all the map's values.


I was thinking you were using this with s/cat for argument specifications, but the same principle applies. Specs are just predicates. It's all functions, all the way down 🙂


I need to define a spec for a map that holds keys owned by multiple parts of my code. So, looking a a tasteful way to build it incrementally from multiple files. (So that each namespace adds in the parts it understands). This strikes me as non-trivial, especially since I can't just have a defonce'd atom that I assoc into. Because s/keys is a macro, I need to assemble only after I've gathered all the parts. Sounds like I need to think about file loading order and other issues that I've ignored until now in my Clojure/Script. Is there a straightforward way to do this? Or am I barking up the wrong trees?


I am not sure what you are asking?


if each key is owned by a different part of your code, and you want to spec each key do that


and then in whatever central place, create your keys spec from each key


the structure of clojure requires you to have a central place, the way the ns macro and everything else works requires you to have a defined load order and explicitly require the code you need access to


does s/coll-of check every element, or does it randomly pick a few and test them ?


> coll-of will exhaustively conform every value


as opposed to every: > Note that ‘every’ does not do exhaustive checking, rather it samples coll-check-limit elements.


been away for a bit - i remember core had some private convenience macro for checking macro invocations. what’s the latest recommendation on that? i actually want to use the spec for parsing inside the macro, but it’s a bit awkward to conform and then if that fails explain, etc


@hiredman - I was looking for a way to avoid having to know about all the parts at one central place.


That is, I don't want to say (s/keys :opt [ns1/key1 ns2/key2 ,,,]), but instead create the spec dynamically. This seems trickier than it should be, since keys is a macro, so I can't just do a trivial atom/assoc/apply dance.


it sounds like you want the already existing feature in spec where a s/keys spec will check specs for keys that exist in the map that have a spec even if they aren't part of the s/keys spec


I assume this is more appropriate for blog post reading rather than discussion: is there a good writeup somewhere of qualified vs unqialified names for specs ? Everything I've done so far in clojure is unqualified, i.e. :foo kws, but looking at spec, it seems like the default / preferred wa yis to be qualified i.e. ::foo or :blah.namespace/foo


I have a uuid. Is there a smart way to bias the generator so I can control the distribution of uuids? i.e. completely random vs. power law?


I’m aware of e.g. gen/elements, was wondering if there’s something else


you're trying to get collisions?


yes, some of the time


but I’d really like e.g. power laws on repeat UUIDs, so out of 1000 uuids, one appears 100 times, one appears 20 times, etc.


reading the spec source was informative. I’ll just with-gen with a UUID constructor


where will you get the args for the constructor?


type 5s are deterministic, and I suspect I can create v1s by specifying a unix time


if you use gen/large-integer and gen/fmap that to the type-3 uuid constructor, that will give you something like the distribution you want


keep in mind how distribution relates to size


can you expand on that?


I also talked about it some here if you liked faces and voices and slides and things


very useful, thank you