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.

Reply via email to