Copy generators impl details from the old cljs code
Most of these are avoiding use of HOFs for performance (at least in
cljs-land). Another was a bad argument name.
Gary Fredericks
8 years ago
66 | 66 | of random number generators." |
67 | 67 | [rr] |
68 | 68 | (lazy-seq |
69 | (let [[r1 r2] (random/split rr)] | |
70 | (cons r1 | |
71 | (lazy-random-states r2))))) | |
69 | (let [[r1 r2] (random/split rr)] | |
70 | (cons r1 | |
71 | (lazy-random-states r2))))) | |
72 | 72 | |
73 | 73 | (defn- gen-seq->seq-gen |
74 | 74 | "Takes a sequence of generators and returns a generator of sequences (er, vectors)." |
83 | 83 | (defn fmap |
84 | 84 | [f gen] |
85 | 85 | (assert (generator? gen) "Second arg to fmap must be a generator") |
86 | (gen-fmap (partial rose/fmap f) gen)) | |
86 | (gen-fmap #(rose/fmap f %) gen)) | |
87 | 87 | |
88 | 88 | |
89 | 89 | (defn return |
134 | 134 | ([generator max-size] |
135 | 135 | (let [r (random/make-random) |
136 | 136 | size-seq (make-size-range-seq max-size)] |
137 | (core/map (comp rose/root #(call-gen generator %1 %2)) | |
137 | (core/map #(rose/root (call-gen generator %1 %2)) | |
138 | 138 | (lazy-random-states r) |
139 | 139 | size-seq)))) |
140 | 140 | |
163 | 163 | |
164 | 164 | (defn- halfs |
165 | 165 | [n] |
166 | (take-while (partial not= 0) (iterate #(quot % 2) n))) | |
166 | (take-while #(not= 0 %) (iterate #(quot % 2) n))) | |
167 | 167 | |
168 | 168 | (defn- shrink-int |
169 | 169 | [integer] |
170 | (core/map (partial - integer) (halfs integer))) | |
170 | (core/map #(- integer %) (halfs integer))) | |
171 | 171 | |
172 | 172 | (defn- int-rose-tree |
173 | 173 | [value] |
272 | 272 | (assert (every? generator? generators) |
273 | 273 | "Arg to one-of must be a collection of generators") |
274 | 274 | (bind (choose 0 (dec (count generators))) |
275 | (partial nth generators))) | |
275 | #(nth generators %))) | |
276 | 276 | |
277 | 277 | (defn- pick |
278 | 278 | [[h & tail] n] |
312 | 312 | #(gen-pure (rose/fmap v %))))) |
313 | 313 | |
314 | 314 | (defn- such-that-helper |
315 | [max-tries pred gen tries-left rand-seed size] | |
315 | [max-tries pred gen tries-left rng size] | |
316 | 316 | (if (zero? tries-left) |
317 | 317 | (throw (ex-info (str "Couldn't satisfy such-that predicate after " |
318 | 318 | max-tries " tries.") {})) |
319 | (let [[r1 r2] (random/split rand-seed) | |
319 | (let [[r1 r2] (random/split rng) | |
320 | 320 | value (call-gen gen r1 size)] |
321 | 321 | (if (pred (rose/root value)) |
322 | 322 | (rose/filter pred value) |
413 | 413 | |
414 | 414 | (def neg-int |
415 | 415 | "Generate negative integers bounded by the generator's `size` parameter." |
416 | (fmap (partial * -1) nat)) | |
416 | (fmap #(* -1 %) nat)) | |
417 | 417 | |
418 | 418 | (def s-pos-int |
419 | 419 | "Generate strictly positive integers bounded by the generator's `size` |
484 | 484 | if it's not already." |
485 | 485 | [coll] |
486 | 486 | (let [index-gen (choose 0 (dec (count coll)))] |
487 | (fmap (partial reduce swap (vec coll)) | |
487 | (fmap #(reduce swap (vec coll) %) | |
488 | 488 | ;; a vector of swap instructions, with count between |
489 | 489 | ;; zero and 2 * count. This means that the average number |
490 | 490 | ;; of instructions is count, which should provide sufficient |
509 | 509 | `key-gen` and values chosen from `val-gen`." |
510 | 510 | [key-gen val-gen] |
511 | 511 | (let [input (vector (tuple key-gen val-gen))] |
512 | (fmap (partial into {}) input))) | |
512 | (fmap #(into {} %) input))) | |
513 | 513 | |
514 | 514 | (defn hash-map |
515 | 515 | "Like clojure.core/hash-map, except the values are generators. |
526 | 526 | vs (take-nth 2 (rest kvs))] |
527 | 527 | (assert (every? generator? vs) |
528 | 528 | "Value args to hash-map must be generators") |
529 | (fmap (partial zipmap ks) | |
529 | (fmap #(zipmap ks %) | |
530 | 530 | (apply tuple vs)))) |
531 | 531 | |
532 | 532 | (def char |