如何创建一个懒惰的随机数序列?
我目前的代码:
(import '(java.util Random))
(def r (new Random))
(defn rnd [_]
(.nextInt r 10))
(defn random-numbers [max]
(iterate #(.nextInt r max) (.nextInt r max)))
(println (take 5 (random-numbers 10)))
执行它会引发异常:
(线程“main”中的异常clojure.lang.ArityException:错误的args(1)传递给:user $ random-numbers $ fn 在clojure.lang.AFn.throwArity(AFn.java:437) 在clojure.lang.AFn.invoke(AFn.java:39) 在clojure.core $ iterate $ fn__3870.invoke(core.clj:2596) 在clojure.lang.LazySeq.sval(LazySeq.java:42) 在clojure.lang.LazySeq.seq(LazySeq.java:60) 在clojure.lang.RT.seq(RT.java:466) 在clojure.core $ seq.invoke(core.clj:133) 在clojure.core $ take $ fn__3836.invoke(core.clj:2499) 在clojure.lang.LazySeq.sval(LazySeq.java:42) 在clojure.lang.LazySeq.seq(LazySeq.java:60) 在clojure.lang.Cons.next(Cons.java:39) 在clojure.lang.RT.next(RT.java:580) 在clojure.core $ next.invoke(core.clj:64) 在clojure.core $ nthnext.invoke(core.clj:2752) 在clojure.core $ print_sequential.invoke(core_print.clj:57) 在clojure.core $ fn__4990.invoke(core_print.clj:140) 在clojure.lang.MultiFn.invoke(MultiFn.java:167) 在clojure.core $ pr_on.invoke(core.clj:3264) 在clojure.core $ pr.invoke(core.clj:3276) 在clojure.lang.AFn.applyToHelper(AFn.java:161) 在clojure.lang.RestFn.applyTo(RestFn.java:132) 在clojure.core $ apply.invoke(core.clj:600) 在clojure.core $ prn.doInvoke(core.clj:3309) 在clojure.lang.RestFn.applyTo(RestFn.java:137) 在clojure.core $ apply.invoke(core.clj:600) 在clojure.core $ println.doInvoke(core.clj:3329) 在clojure.lang.RestFn.invoke(RestFn.java:408) 在用户$ eval7.invoke(testing.clj:12) 在clojure.lang.Compiler.eval(Compiler.java:6465) 在clojure.lang.Compiler.load(Compiler.java:6902) 在clojure.lang.Compiler.loadFile(Compiler.java:6863) 在clojure.main $ load_script.invoke(main.clj:282) 在clojure.main $ script_opt.invoke(main.clj:342) 在clojure.main $ main.doInvoke(main.clj:426) 在clojure.lang.RestFn.invoke(RestFn.java:408) 在clojure.lang.Var.invoke(Var.java:401) 在clojure.lang.AFn.applyToHelper(AFn.java:161) 在clojure.lang.Var.applyTo(Var.java:518) 在clojure.main.main(main.java:37) [完成3.8s,退出代码1]
这是一个完全错误的方法,因为我使用的是state,即r是java.util.Random的一个实例,还是只是一个nooby语法错误?
我只是在研究自己的咒语,所以请耐心等我:)。
答案 0 :(得分:29)
repeatedly
非常适合重复运行函数并在seq中收集结果
user> (take 10 (repeatedly #(rand-int 42)))
(14 0 38 14 37 6 37 32 38 22)
至于你的原始方法:iterate接受一个参数,将它提供给一个函数,然后获取结果并将其传递回同一个函数。我在这里并不完全是你想要的,因为你使用的功能并不需要任何参数。你当然可以为它提供占位符并让它工作,尽管repeatedly
可能更合适。
(defn random-numbers [max]
(iterate (fn [ignored-arg] (.nextInt r max)) (.nextInt r max)))
#'user/random-numbers
user> (println (take 5 (random-numbers 10)))
(3 0 0 2 0)
答案 1 :(得分:6)
作为一般指南,不要从Java的类/函数开始。首先查看Clojure在clojure中的核心函数和命名空间。*(然后在贡献的命名空间中,现在使用模块化存储库:请参阅http://dev.clojure.org/display/doc/Clojure+Contrib); rand-int本身在clojure-core中很容易获得。那么,如何开始搜索随机数助手?
使用Clojure 1.3以后,您可以“使用”clojure-repl命名空间来访问方便的apropos函数(与Unix / linux中的apropos命令一样使用); apropos返回到目前为止加载的命名空间中所有匹配的def。
user> (use 'clojure.repl)
nil
user> (apropos "rand")
(rand rand-int rand-nth)
clojure.repl中的find-doc函数也是另一种选择。
另一个指针是在www.clojuredocs.org上搜索,其中包括clojure core和clojure中funcs的用法示例。*。
答案 2 :(得分:0)
至少为了测试目的,能够重复随机的#34;通过播种发电机的顺序。新的spec
库以这种方式报告其测试结果。
本机Clojure函数不允许您为随机序列设定种子,因此我们必须使用底层的Java函数:
(defn random-int-seq
"Generates a reproducible sequence of 'random' integers (actually longs)
from an integer (long) seed. Supplies its own random seed if need be."
([] (random-int-seq (rand-int Integer/MAX_VALUE)))
([seed]
(let [gen (java.util.Random. seed)]
(repeatedly #(.nextLong gen)))))
答案 3 :(得分:0)
让我们使用换能器吗?
(def xf (map (fn [x] (* 10 (rand)))))
我们也可以将rand-int
用作:
(def xf (map (fn [x] (* 10 (rand-int 10)))))
要使用它来生成延迟序列,我们将使用sequence
(sequence xf (range))
这将返回一个懒惰的随机数序列。要获得完整的 n个数字序列,我们可以使用take
作为:
(take n (sequence xf (range)))