为什么Clojure的范围只迭代32次?

时间:2013-12-15 11:33:57

标签: loops for-loop clojure range

这个Clojure代码输出32而我期望100.为什么会这样?使用计数器进行循环的好方法是什么?

(def t 0)
(for [i (range 100)]
  (def t (+ 1 t))
  )
(println t)

2 个答案:

答案 0 :(得分:5)

for评估为懒惰序列。由于称为分块的东西,你在这里很幸运,for被分成32个元素的惰性分区。

您问题中的代码非常不恰当。

在您的情况下,您只需拨打(println 100)

即可

如果您想循环某个副作用的序列,那么您可以使用doseq

(doseq [i (range 100)]
  (println i))

;; or

(dotimes [i 100]
  (println i))

答案 1 :(得分:5)

一些注释:

    在clojure中的
  • for是懒惰的,这意味着它会返回一个懒惰的seq。因为clojure中的lazy seqs是chunked,你看到的是对第一个chunk的评估。
  • 您通常不希望在使用for或map(因为他们的懒惰)时有副作用。为避免这种情况,您应使用doseq或至少doall
  • 你也不想在函数内部进行def,这不是在clojure中做事的正确方法。你应该使用更实用的方法,或者(如果合适的话)使用clojure的状态结构之一(例如atomsagents

这是一种更恰当的方式来获得你想要的东西:

; a more functional way
(def t (reduce + (take 100 (repeat 1)))) 
(println t) 

; a more "stateful" approach
(def t (atom 0))
(doseq [i (range 100)]
  (swap! t inc))

(println @t)