2012-07-30 50 views
10

如何創建一個隨機數的惰性序列?如何在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))) 

執行它拋出異常:

(在線程 「主」 clojure.lang.ArityException異常:ARGS(1)傳遞到的錯誤數量: user $ random-numbers $ fn at clojure.lang.AFn.throwArity(AFn.java:437) at 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) 在clojure.lang.LazySeq.seq(LazySeq.java:60) 在clojure.lang.RT.seq(RT.java:466) 在clojure.core $起。 invoke(core.clj:133) at clojure.core $ take $ fn _3836.invoke(core.clj:2499) at clojure.lang.LazySeq.sval(LazySeq.java:42) at clojure.lang。 LazySeq.seq(LazySeq.java:60) at clojure.lang.Cons.next(Cons.java:39) at clojure.lang.RT.next(RT.java:580) at clojure.core $ next。在clojure.core $ nthnext.invoke(core.clj:2752) clojure.core $ print_sequential.invoke(core_print.clj:57) $ fn__4990.invoke(core.clj:64) 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) at clojure.core $ apply.invoke(core.clj:600) at clojure。核心$ prn.doInvoke(core.clj:3309) at clojure.lang.RestFn.applyTo(RestFn.java:137) at clojure.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) at clojure.lang.Compiler.eval(比較(編譯器.java:6602) 在clojure.lang.Compiler.loadFile(Compiler.java:6863) at clojure.main $ load_script.invoke(main。在clojure.main $ main.doInvoke(main.clj:426)處使用clojure.main $ script_opt.invoke(main.clj:342) 。clojure.lang.RestFn.invoke(RestFn.java:282) at clojure.main $ main.doInvoke(main.clj:426) 408) at clojure.lang.Var.invoke(Var.java:401) at clojure.lang.AFn.applyToHelper(AFn.java:161) at clojure.lang.Var.applyTo(Var.java:518) at clojure.main.main(main.java:37) [在3.8s中完成並帶有退出代碼1]

這是一個完全錯誤的方法,因爲我正在使用狀態,即r是java.util.Random的一個實例,還是它只是一個nooby語法錯誤?

我只是在研究自己的clojure,所以請裸露我:)。

+0

感謝包括整個堆棧跟蹤。這裏並不是真的有必要,但它可以幫助很大,而且往往人們不會打擾。 – amalloy 2012-07-31 18:36:06

回答

28

repeatedly反覆運行的功能,並在SEQ

user> (take 10 (repeatedly #(rand-int 42))) 
(14 0 38 14 37 6 37 32 38 22) 

爲您原始的方法收集的結果是巨大的:迭代需要一個參數,它送至一個函數,然後需要的是結果,將其傳遞迴相同的功能。我不是很想在這裏,因爲你使用的函數不需要任何參數。你當然可以給它一個佔位符,並讓它工作,儘管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) 
6

作爲一般指南,不要從Java的類/函數開始。首先查看Clojure的clojure核心函數和名稱空間*(然後在現在處於模塊化庫中的貢獻名稱空間中:請參閱http://dev.clojure.org/display/doc/Clojure+Contrib); rand-int本身在clojure-core中很容易獲得。那麼,如何開始尋找一個隨機數字助手?你可以使用clojure-repl命名空間訪問方便的apropos函數(與Unix/linux中的apropos命令使用相同的精神);使用clojure-repl命名空間可以訪問方便的apropos函數。 apropos返回目前加載的名稱空間中的所有匹配的defs。

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

clojure.repl中的find-doc函數也是另一種選擇。

另一個指針是在www.clojuredocs.org上進行搜索,其中包括clojure core和clojure的funcs例子。

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