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
A clean way:
(ns designed.ly.rand)
(def ^:dynamic *rand* clojure.core/rand)
(defn rand-1
([]
(*rand* 1))
([n]
(*rand* n)))
(defmacro with-rand-seed
"Sets seed for calls to random in body. Beware of lazy seqs!"
[seed & body]
`(let [g# (java.util.Random. ~seed)]
(binding [*rand* #(* % (.nextFloat g#))]
(with-redefs [rand rand-1]
~@body))))
It redefines rand within the scope. Example:
(with-rand-seed 9
(rand 4) ; => 2.9206461906433105
(rand-int 10)) ; => 2
BTW. Beware of lazy seqs: http://kotka.de/blog/2009/11/Taming_the_Bound_Seq.html (Apparently, this link redirects to https without a trusted certificate so here's a link to a version at Web Archive: https://web.archive.org/web/20120505012701/http://kotka.de/blog/2009/11/Taming_the_Bound_Seq.html).