简体   繁体   中英

Clojure: How to prevent a process from running forever?

Basically, I am trying to generate n number of random number and use them as indices to return elements in the the sequence (range n) and I also want to keep adding them up on the fly by using reduce . The first 2 expressions return results relatively quickly. However, the 3rd expression takes forever to run, which I have no idea why. Does this have anything to with laziness , which is a concept that I never understand. If it does, please also elaborate on what laziness really means.

(reduce + (map #(nth (range 1000) %) (repeatedly 1000 #(rand-int 1000))))
504750
 (reduce + (map #(nth (range 10000) %) (repeatedly 10000 #(rand-int 10000))))
50334424
(reduce + (map #(nth (range 100000) %) (repeatedly 100000 #(rand-int 100000))))
;; this takes forever

And is there way to make sure the third line of expression return a definite answer without hanging in there forever ?

Few mistakes here.

(range n) returns a sequence, nth function gives indexed access to collection. Of course sequence doesn't know anything about index, so your nth works in O(n) time To make nth a linear solution, transform seq to vector (vec (range n))

Every time to access an item in a collection you create a new range, what is not optimal.

Your 2nd case:

(time  (reduce + (map #(nth (range 10000) %) (repeatedly 10000 #(rand-int 10000)))))
"Elapsed time: 4055.15506 msecs"

Improved version:

(time(reduce + (let [array (vec (range 10000))] 
                 (repeatedly 10000 #(nth array (rand-int 10000))))))
"Elapsed time: 5.134413 msecs"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM