Skip to content

Instantly share code, notes, and snippets.

@bmabey
Last active August 29, 2015 14:06
Show Gist options
  • Save bmabey/2b25c6c684b3e374a3a1 to your computer and use it in GitHub Desktop.
Save bmabey/2b25c6c684b3e374a3a1 to your computer and use it in GitHub Desktop.
sublist generator for clojure test.check... which has better shrinking properites?
;; 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))
@bmabey
Copy link
Author

bmabey commented Sep 18, 2014

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?

@reiddraper
Copy link

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