2011-09-29 28 views
7

這一個已經困擾了我一段時間了, 我們應該如何在一組或映射中的值在存儲循環?Clojure的for循環,存儲值在一組或地圖

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

我知道這是不行的,但我想一個類似的功能,其中一套最終將包含[0] [0 1] ... [0 9] [1:0] .. [9 9]

謝謝

+0

謝謝大家,您的答覆。 – KaKa

回答

13

如果我正確理解你的問題,你需要把你的表達由內向外:

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

這裏是實現的事情這for不像for循環中像Java和C

0

clojure有幾個偉大的系統管理可變狀態。在這種情況下,你可能要包含一系列的atom

你的其他選項有:

  • 一個ref如果超過一個變化需要作出(協調的多線程)
  • 一個var如果這將是單線程的,如果你想設置s的值異步
(一個VAR可以很好的工作在這裏作爲一個原子)
  • 當然for已經返回一個序列,所以你可能只是想

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

    這裏的第一個代碼片段沒有任何意義,據我所知?這不是一個使用'swap!'的有效方法,正如你後來提到的那樣,它不是一個好主意。 – amalloy

    +0

    無論如何,第一個snipit並不是真正的答案,所以我只是刪除它。冒充測試* tisk tisk * –

    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]))  
    

    你最終將與一組對。

    5

    一般當你想返回一組或一個地圖或其他「單值」,是不是從一個序列一「重複」廣義操作的序列,使用reduce是更地道/直白比loop/recur,和for總是返回序列(不是集合或映射)。

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

    注意,(對於..)這裏僅用於產生含有所有值來編譯成單個結果設置一個起。或者,例如:

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

    我想你也可以在這種情況下使用一些瞬態數據結構。

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

    只是一個代碼示例,未經過測試。

    +1

    這是不正確的。從[瞬變的文檔](http://clojure.org/transients):「特別要注意的是,暫態不是被設計爲在現場進行的,你必須在下次調用中捕獲和使用返回值。它們支持與它們替換的功能性持久代碼相同的代碼結構「。 – Jonas