如何在clojure中创建随机数的惰性序列

如何在clojure中创建随机数的惰性序列,clojure,Clojure,如何创建随机数的惰性序列 我当前的代码: (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”clo

如何创建随机数的惰性序列

我当前的代码:

(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中的异常:传递给用户的参数(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) 下一步(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\u sequential.invoke(core\u print.clj:57) 在clojure.core$fn_uu4990.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) 加载(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语法错误


我只是自学clojure,所以请耐心听我说:)。

反复
非常适合反复运行函数并将结果收集到序列中

user> (take 10 (repeatedly #(rand-int 42)))
(14 0 38 14 37 6 37 32 38 22)
至于您最初的方法:iterate接受一个参数,将其反馈给一个函数,然后接受该参数的结果并将其传递回同一个函数。我不太清楚您在这里想要什么,因为您使用的函数不需要任何参数。当然,您可以为该参数指定一个占位符并使其工作,尽管反复使用
可能更合适

(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)

作为一般指南,不要从Java中的类/函数开始。首先看Clojure.*中Clojure的核心函数和名称空间(然后看现在模块化repos中提供的名称空间:参见);兰德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的使用示例。*

至少出于测试目的,可以通过种子设定生成器来重复“随机”序列。新的
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))))) 

让我们用一个传感器,好吗

 (def xf (map (fn [x] (* 10 (rand)))))
我们还可以使用
rand int
作为:

(def xf (map (fn [x] (* 10 (rand-int 10)))))
(take n (sequence xf (range)))
要使用它生成惰性序列,我们将使用
sequence

(sequence xf (range))
这将返回一个随机数的惰性序列。要获得n个数字的完整序列,我们可以使用
为:

(def xf (map (fn [x] (* 10 (rand-int 10)))))
(take n (sequence xf (range)))

谢谢你包含了整个stacktrace。在这里,这并不是真的必要,但它可以极大地帮助人们,而且人们通常不必费心。嗨!请您解释一下变量
[x]
在您的两个
xf
定义中的作用好吗?对我来说,它们似乎没有任何效果,
xf
可能没有参数(即
(def xf[])
,但我对Clojure是新手,可能错过了一些值得学习的东西:-)在映射中传递的函数需要一个参数,以便它可以映射到它上面。更简单的是,用
fn[\u]
代替
fn[x]
好,否则,我们将
(范围)
的输出传递给我们的自定义函数,该函数对生成的值不做任何处理,而是返回一个随机值;这很聪明。谢谢你的澄清!