How to generate repeatable random sequences with rand-int
clojure
Solution
Probably not the cleanest way, but you can make it work by redefining `clojure.core/rand`:
(ns clojure.core)
(def r (java.util.Random. 1))
(defn rand
([] (.nextDouble r))
([n] (.nextInt r n)))
(take 10 (repeatedly #(rand-int 10)))
This produces (5 8 7 3 4 4 4 6 8 8) every time I run it.
Problem
I want to be able to generate repeatable numbers using `rand` in Clojure. (Specifically, I want results of calls to `rand-nth` or Incanter's `sample` to be repeatable, and these call `rand-int` which in turn calls `rand`). I figured out from this question that if I use clojure.data.generators, I can reset the random state: ``` (require '[clojure.data.generators :as gen]) (alter-var-root #'gen/*rnd* (constantly (java.util.Random. 437))) (gen/reservoir-sample 5 (range 1000)) ; => [940 591 636 12 755] (gen/reservoir-sample 5 (range 1000)) ; => [376 540 827 307 463] ; reset random state: (alter-var-root #'gen/*rnd* (constantly (java.util.Random. 437))) ; now the same results are generated again: (gen/reservoir-sample 5 (range 1000)) ; => [940 591 636 12 755] (gen/reservoir-sample 5 (range 1000)) ; => [376 540 827 307 463] ``` However, that method only seems to affect functions in clojure.data.generators, which isn't surprising: ``` (alter-var-root #'gen/*rnd* (constantly (java.util.Random. 437))) (rand) ; => 0.9372552374760151 (rand) ; => 0.2712729314667742 ; reset random state: (alter-var-root #'gen/*rnd* (constantly (java.util.Random. 437))) ; not same results as before: (rand) ; => 0.630238593767316 (rand) ; => 0.426744420572015 ``` How can I restore the random state in such as way as to get repeatable results from `rand`? So far I haven't found any documentation about this. (Another question sounds as if it might be the same issue, but it's asking about something completely different.)