基本上,我正在尝试生成n
个随机数,并将它们用作索引来返回序列(range n)
中的元素,我还希望通过使用它来保持随意添加它们reduce
。
前两个表达式相对较快地返回结果。但是,第3个表达式需要永远运行,我不明白为什么。这与懒惰有什么关系,这是我从未理解的概念。如果确实如此,请详细说明懒惰的真正含义。
(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
有没有办法确保第三行表达式在没有永远挂在那里的情况下返回一个明确的答案?
答案 0 :(得分:3)
这里几乎没有错误。
(range n)
返回一个序列,nth
函数为索引提供对集合的访问权限。
当然,序列对索引一无所知,因此nth
在O(n)
时间内有效
要使nth
成为线性解,请将seq转换为向量(vec (range n))
每次访问集合中的项目时,都会创建一个新的范围,这不是最佳范围。
你的第二个案例:
(time (reduce + (map #(nth (range 10000) %) (repeatedly 10000 #(rand-int 10000)))))
"Elapsed time: 4055.15506 msecs"
改进版本:
(time(reduce + (let [array (vec (range 10000))]
(repeatedly 10000 #(nth array (rand-int 10000))))))
"Elapsed time: 5.134413 msecs"