11

如何创建一个惰性随机数序列?

我当前的代码:

(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 中的异常:传递给:clojure.lang.AFn.throwArity 的 user$random-numbers$fn 的错误数量的 args (1)(AFn.java:437)在 clojure.lang。 AFn.invoke(AFn.java:39) at clojure.core$iterate$fn__3870.invoke(core.clj:2596) at clojure.lang.LazySeq.sval(LazySeq.java:42) at 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) at clojure.core$fn__4990.invoke(core_print.clj:140) at clojure.lang.MultiFn.invoke(MultiFn.java:167) at clojure.core$pr_on.invoke (core.clj:3264) at clojure.core$pr.invoke(core.clj:3276) at clojure.lang.AFn.applyToHelper(AFn.java:161) at clojure.lang.RestFn.applyTo(RestFn.java: 132) 在 clojure.lang.RestFn.applyTo(RestFn.java:137) 的 clojure.core$prn.doInvoke(core.clj:3309) 的 clojure.core$apply.invoke(core.clj:600)。 core$apply.invoke(core.clj:600) at clojure.core$println.doInvoke(core.clj:3329) at clojure.lang.RestFn.invoke(RestFn.java:408) at user$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) at clojure.main$load_script.invoke(main.clj:282) at clojure.main$script_opt.invoke(main.clj:342) at 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.8 秒内完成,退出代码为 1]java:518) at clojure.main.main(main.java:37) [在 3.8 秒内完成,退出代码为 1]java:518) at clojure.main.main(main.java:37) [在 3.8 秒内完成,退出代码为 1]

这是一个完全错误的方法,因为我正在使用状态,即 r 是 java.util.Random 的一个实例,还是只是一个 nooby 语法错误?

我只是在自己研究clojure,所以请多多包涵:)。

4

4 回答 4

31

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)
于 2012-07-30T23:40:57.240 回答
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 返回到目前为止加载的命名空间中的所有匹配定义。

user> (use 'clojure.repl)
nil
user> (apropos "rand")
(rand rand-int rand-nth)

clojure.repl 中的 find-doc 函数也是另一种选择。

另一个指针是在 www.clojuredocs.org 上搜索,其中包括 clojure core 和 clojure.* 中的函数的用法示例。

于 2012-08-01T23:25:27.103 回答
0

至少出于测试目的,能够通过播种生成器来重复“随机”序列是很好的。新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))))) 
于 2017-07-31T10:46:11.503 回答
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)))
于 2017-08-01T08:07:32.173 回答