It also might be helpful to know that there is already a subset generator available in this library <https://github.com/gfredericks/test.chuck#generators>.
Gary On Saturday, July 25, 2015 at 6:54:59 PM UTC-5, Carlo wrote: > > Hey Mayank! > > What you've done here might appear to work, but it will get you into > trouble when test.check starts to shrink your inputs. When test.check runs > your generators it relies you you using it as your only source of > randomness, and so your use of `rand-int` will cause some problems. > > The trick is to use the `bind` function to make a generator which depends > on the value of another generator (in this case, to capture the generated > map so you can call rand-subset with the correct set of keys): > > (defn rand-subset > "Given a collection coll > it'll generate a random subset." > [coll] > (gen/fmap (fn [i] (combo/nth-subset coll i)) > (gen/choose 0 (dec (combo/count-subsets coll))))) > > (defn gen-varying-map > "Given a generator which generates a map, > it'll randomly select keys from it thus making it > varying-sized map. > Note: It can return empty maps as well." > [map-gen] > (gen/bind map-gen > (fn [map] > (gen/fmap (fn [keyseq] > (select-keys map keyseq)) > (rand-subset (keys map)))))) > > (gen/sample (gen-varying-map (gen/hash-map > "user" (gen/such-that not-empty > gen/string-alpha-numeric) > "level" gen/nat > "timezone" gen/pos-int))) > => > ({"user" "e", "level" 0} > {"level" 1} > {"user" "M1"} > {"timezone" 2} > {"user" "2", "level" 2, "timezone" 0} > {"timezone" 3} > {"user" "W", "level" 5, "timezone" 0} > {"timezone" 5} > {} > {}) > > This output appears the same as yours, but it will produce predictable > shrink trees, and thus will shrink more effectively. > > Carlo > > On 26 July 2015 at 07:10, Mayank Jain <fires...@gmail.com <javascript:>> > wrote: > >> Hi, >> >> I would like to generate variable sized map using test.check i.e. >> given any generator which generates a map, it should randomly select-keys >> from it. >> >> Here's what I've come up with so far: >> >> >>> (ns proj.util >> (:require [clojure.test.check.generators :as gen] >> [clojure.math.combinatorics :as combo])) >> >> (defn rand-subset >> "Given a collection coll, >> it'll generate a random subset." >> [coll] >> (->> coll >> combo/count-subsets >> rand-int >> (combo/nth-subset coll))) >> >> (defn gen-varying-map >> "Given a generator which generates a map, >> it'll randomly select keys from it thus making it >> varying-sized map. >> Note: It can return empty maps as well." >> [map-gen] >> (gen/fmap (fn [m] >> (let [ks (rand-subset (keys m))] >> (select-keys m ks))) >> map-gen)) >> >> Here's an example output, >> (gen/sample (gen-varying-map (gen/hash-map >> "user" (gen/such-that not-empty >> >> gen/string-alphanumeric) >> "level" gen/nat >> "timezone" gen/pos-int))) >> => >> ({"user" "1"} >> {"user" "l8", "level" 0, "timezone" 1} >> {"level" 1} >> {"user" "oA", "timezone" 0} >> {"level" 2, "timezone" 1} >> {"level" 5} >> {"user" "8aP", "level" 5, "timezone" 6} >> {"user" "035rqi", "level" 7} >> {"timezone" 4} >> {"timezone" 2}) >> >> My question is, is this the right way? Or is there a better way to do it? >> >> Thanks :) >> >> -- >> You received this message because you are subscribed to the Google >> Groups "Clojure" group. >> To post to this group, send email to clo...@googlegroups.com >> <javascript:> >> Note that posts from new members are moderated - please be patient with >> your first post. >> To unsubscribe from this group, send email to >> clojure+u...@googlegroups.com <javascript:> >> For more options, visit this group at >> http://groups.google.com/group/clojure?hl=en >> --- >> You received this message because you are subscribed to the Google Groups >> "Clojure" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to clojure+u...@googlegroups.com <javascript:>. >> For more options, visit https://groups.google.com/d/optout. >> > > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.