Last active
August 29, 2015 14:06
-
-
Save bmabey/2b25c6c684b3e374a3a1 to your computer and use it in GitHub Desktop.
sublist generator for clojure test.check... which has better shrinking properites?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; my first version taking advantage of the new shuffle generator introduced in 0.6... | |
(defn sublist1 | |
[coll] | |
(-> (gen/tuple (gen/shuffle coll) (gen/choose 0 (count coll))) | |
(gen/bind (fn [[coll* how-many]] | |
(gen/return (take how-many coll*)))))) | |
;; version inspired by http://roberto-aloi.com/erlang/notes-on-erlang-quickcheck/ | |
;; sublist(L0) -> | |
;; ?LET(L, [{E, eqc_gen:bool()} || E <- L0], [X || {X, true} <- L]). | |
(defn sublist2 [coll] | |
(-> (gen/vector gen/boolean 0 (count coll)) | |
(gen/bind (fn [bools] | |
(->> bools | |
(keep-indexed (fn [i b] (when b (coll i)))) | |
gen/return))))) | |
(gen/sample (g/sublist2 [:a :b :c :d :e :f :g :h :i :j :k])) ; => ((:a :b) (:a) () (:b) () (:a :b :c :d :f :j) (:a :c) (:c) (:a :f :g) (:a :d)) | |
sublist2
should shrink better, yes. You can simplify it's definition a little bit too, since your gen/bind
call ends with gen/return
, you can simply use gen/fmap
and remove the call to gen/return
.
Thanks for the feedback @reiddraper!
Are you suggesting that I use fmap
in place of bind
too (since fmap takes a generator)? I don't see how to do that since I also need an index for collection lookup as well. So I would either need a fmap-indexed
or fmap
be variadic so I could zip an index in. What am I missing?
Words are hard, code is easier:
(defn sublist [coll]
(gen/fmap
(fn [bools] (keep-indexed (fn [i b] (when b (coll i))) bools))
(gen/vector gen/boolean (count coll))))
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I'm inclined to think that
sublist2
would be better since it does less work but I haven't dug into how shrinking actually works so that is a total guess.