537 | 537 |
|
538 | 538 |
(defn ^:private coll-distinct-by*
|
539 | 539 |
"Returns a rose tree."
|
540 | |
[empty-coll key-fn shuffle-fn gen rng size num-elements max-tries]
|
|
540 |
[empty-coll key-fn shuffle-fn gen rng size num-elements min-elements max-tries]
|
541 | 541 |
{:pre [gen (:gen gen)]}
|
542 | 542 |
(loop [rose-trees (transient [])
|
543 | 543 |
s (transient #{})
|
544 | 544 |
rng rng
|
545 | 545 |
size size
|
546 | 546 |
tries 0]
|
547 | |
(cond (= max-tries tries)
|
548 | |
(throw (ex-info "Couldn't generate enough distinct elements!"
|
549 | |
{:gen gen, :max-tries max-tries}))
|
550 | |
|
551 | |
(= (count rose-trees) num-elements)
|
|
547 |
(cond (and (= max-tries tries)
|
|
548 |
(< (count rose-trees) min-elements))
|
|
549 |
(throw (ex-info "Couldn't generate enough distinct elements!"))
|
|
550 |
|
|
551 |
|
|
552 |
(or (= max-tries tries)
|
|
553 |
(= (count rose-trees) num-elements))
|
552 | 554 |
(->> (persistent! rose-trees)
|
553 | 555 |
;; we shuffle the rose trees so that we aren't biased
|
554 | 556 |
;; toward generating "smaller" elements earlier in the
|
|
604 | 606 |
{:keys [num-elements min-elements max-elements max-tries] :or {max-tries 10}}]
|
605 | 607 |
(let [shuffle-fn (if ordered?
|
606 | 608 |
the-shuffle-fn
|
607 | |
(fn [_rng coll] coll))]
|
|
609 |
(fn [_rng coll] coll))
|
|
610 |
hard-min-elements (or num-elements min-elements 1)]
|
608 | 611 |
(if num-elements
|
609 | 612 |
(let [size-pred #(= num-elements (count %))]
|
610 | 613 |
(assert (and (nil? min-elements) (nil? max-elements)))
|
|
617 | 620 |
;; step?
|
618 | 621 |
(every-pred size-pred #(distinct-by? key-fn %))
|
619 | 622 |
size-pred)
|
620 | |
(coll-distinct-by* empty-coll key-fn shuffle-fn gen
|
621 | |
rng gen-size num-elements max-tries)))))
|
|
623 |
(coll-distinct-by* empty-coll key-fn shuffle-fn gen rng gen-size
|
|
624 |
num-elements hard-min-elements max-tries)))))
|
622 | 625 |
(let [min-elements (or min-elements 0)
|
623 | 626 |
size-pred (if max-elements
|
624 | 627 |
#(<= min-elements (count %) max-elements)
|
|
636 | 639 |
;; same comment as above
|
637 | 640 |
(every-pred size-pred #(distinct-by? key-fn %))
|
638 | 641 |
size-pred)
|
639 | |
(coll-distinct-by* empty-coll key-fn shuffle-fn gen
|
640 | |
rng gen-size num-elements max-tries)))))))))))
|
|
642 |
(coll-distinct-by* empty-coll key-fn shuffle-fn gen rng gen-size
|
|
643 |
num-elements hard-min-elements max-tries)))))))))))
|
641 | 644 |
|
642 | 645 |
|
643 | 646 |
;; I tried to reduce the duplication in these docstrings with a macro,
|