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 <[email protected] <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 [email protected]
>> <javascript:>
>> Note that posts from new members are moderated - please be patient with
>> your first post.
>> To unsubscribe from this group, send email to
>> [email protected] <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 [email protected] <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 [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
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 [email protected].
For more options, visit https://groups.google.com/d/optout.