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

Jay*_*man 2 loops for-loop clojure range

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

(def t 0)
(for [i (range 100)]
  (def t (+ 1 t))
  )
(println t)
Run Code Online (Sandbox Code Playgroud)

Ale*_*sky 5

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

您的问题中的代码非常非惯用.

在你的情况下你可以打电话 (println 100)

如果你想循环一个序列的一些副作用,那么你可以使用 doseq

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

;; or

(dotimes [i 100]
  (println i))
Run Code Online (Sandbox Code Playgroud)

  • @JayForeman前往4clojure.com并完成所有简单和中等的工作,查看前10名左右的其他人的解决方案.到那时你会得到它. (2认同)

Shl*_*omi 5

几点说明:

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

这是获得你想要的更惯用的方式:

; 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)
Run Code Online (Sandbox Code Playgroud)