clojure-spec

About: http://clojure.org/about/spec Guide: http://clojure.org/guides/spec API: https://clojure.github.io/spec.alpha/clojure.spec.alpha-api.html
2020-08-28T00:02:14.119300Z

also is there a way to get the generators for different items in a nested map to be consistent? i.e. for instance if i had a map like:

(s/def ::begin-date inst?)
(s/def ::end-date inst?)

(s/def ::dates (s/keys :req-un [::begin-date ::end-date]))
how can i get begin-date to be less than end-date in the generated output? sorry if this is documented somewhere ๐Ÿ™‚

2020-08-28T00:02:38.119800Z

^ appreciate the help in advance ๐Ÿ™ ๐Ÿ˜„

seancorfield 2020-08-28T00:29:11.121Z

@lpanda2014 You can wrap the s/keys part with s/and and add a predicate to check that #(some-date-lib/after? (::begin-date %) (::end-date %))

seancorfield 2020-08-28T00:30:00.121900Z

(most of the date utility libraries have a simple function to check if one date is after another -- don't know what or if you're using)

kenny 2020-08-28T00:31:34.122900Z

or built in to Date: #(.after (::end-date %) (::begin-date %))

kenny 2020-08-28T00:35:04.123600Z

Needs a custom gen too. Something like (gen/fmap #(zipmap [:begin-date :end-date] (sort %)) (s/gen (s/tuple inst? inst?)))

2020-08-28T00:41:52.123800Z

thanks! this worked like a charm

(s/def ::dates (s/with-gen
                  (s/keys :req-un [::begin-date ::end-date])
                   #(gen/fmap (fn [d] (zipmap [:begin-date :end-date] (sort d))) (s/gen (s/tuple inst? inst?)))))

kenny 2020-08-28T00:42:27.124Z

You'll still (probably) want the predicate added with s/and

2020-08-28T00:45:27.124200Z

thanks! for some reason that didnโ€™t work though ๐Ÿ˜ž had to change it to ints since i dont have a datetime library in my repl but the below code gave me a null ptr when i went to generate. is my syntax off?

(s/def ::begin-date int?)
  (s/def ::end-date int?)
  (s/def ::dates (s/and
                  (s/keys :req-un [::begin-date ::end-date])
                  #(> (::end-date %) (::begin-date %))))

(gen/generate (s/gen ::dates)) ;; broken

2020-08-28T00:46:03.124400Z

hm i couldnโ€™t get the s/and part to work actually

kenny 2020-08-28T00:46:45.124700Z

(s/and ::dates #(.after (::end-date %) (::begin-date %)))

2020-08-28T00:50:32.124900Z

actually nvm figured it out - the second predicate canโ€™t be :: ๐Ÿ™‚ thanks for your help!

2020-08-28T00:50:59.125100Z

thanks !

seancorfield 2020-08-28T01:06:56.125300Z

https://github.com/stackoverflow/date-clj is a simple library for manipulating dates, that has before/after comparisons. We use that at work.

seancorfield 2020-08-28T01:08:04.126200Z

Ah, good point. I couldn't remember whether java.util.Date had comparison built-in (and was too lazy to check the Java API docs ๐Ÿ™‚ )

alexmiller 2020-08-28T01:53:04.127200Z

A set is a valid spec that gens. So override the generator to gen from a known set of names