clojure for循环,将值存储在集合或映射中

时间:2011-09-29 17:53:59

标签: loops functional-programming clojure immutability

这一次困扰我一段时间了, 我们应该如何在for循环中的集合或映射中存储值?

(let [s #{}]
     (for [ i (range 10)
            j (range 10) ]
      (into s [i j])))

我知道这不起作用,但我想要一个与此类似的功能,其中该组最终将包含[0 0] [0 1] ... [0 9] [1 0] ... [9 9 ]

由于

5 个答案:

答案 0 :(得分:14)

如果我正确理解你的问题,你需要将你的表达从内到外:

(let [s #{}]
  (into s (for [i (range 10) 
                j (range 10)] 
            [i j])))

这里要认识到的是for返回一个值(一个懒惰的序列),而不像Java和C等更多命令式语言中的for循环。

答案 1 :(得分:6)

这是你想要的吗?

(into #{} (for [i (range 10) j (range 10)]
  [i j]))
;-> #{[2 1] [3 2] [4 3] [5 4] [6 5] [7 6] [8 7] [9 8] [1 0]
;     [2 2] [3 3] [4 4] [5 5] [6 6]...

如果您只想将列表作为一组:

(set (for [i (range 10) j (range 10)]
  [i j]))    

你最终会得到一组对。

答案 2 :(得分:5)

通常当你想要使用reduce从seq上的'重复'广义操作返回不是seq的集合或地图或其他“单个值”时比loop/recur更惯用/更直接,for总是返回seq(不是集合或地图)。

(reduce conj #{} (for [i (range 10) j (range 10)] [i j]))

请注意,(for ..)此处仅用于生成包含要编译为单个结果 set 的所有值的seq。或者,例如:

(reduce + 0 (range 100))
=> 4950

答案 3 :(得分:0)

clojure有几个很好的系统来管理可变状态。在这种情况下,您可能需要atom包含一组

您的其他选择是:

  • a ref如果需要进行多次更改(协调多个线程)
  • 一个var如果这是单线程的(var可能在这里与原子一样好)
  • agent如果您想异步设置s的值

当然for已经返回一个序列,所以你可能只想要

 (into #{} (for [ i (range 10)
                  j (range 10) ]
             [i j]))

答案 4 :(得分:0)

我认为在这种情况下你也可以使用一些瞬态数据结构。

(let [s (transient #{})]
 (for [ i (range 10)
        j (range 10) ]
  (assoc! s i j)))
(persistent! s)

只是一个代码示例,未经过测试。