Clojure для цикла, сохранить значения в наборе или карте - PullRequest
8 голосов
/ 29 сентября 2011

Этот уже давно беспокоит меня, Как сохранить значение в наборе или карте в цикле 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 ]

14 голосов
/ 29 сентября 2011

Если я правильно понимаю ваш вопрос, вам нужно вывернуть выражение наизнанку:

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

Здесь нужно понять, что for возвращает значение (ленивая последовательность) в отличие от циклов for в более обязательных языках, таких как Java и C.

6 голосов
/ 29 сентября 2011

Это то, что вы хотите?

(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 голосов
/ 29 сентября 2011

Обычно , если вы хотите вернуть набор, карту или другое «отдельное значение», которое не является последовательностью из «повторной» обобщенной операции в последовательности, использование reduce более идиоматично/ прямолинейнее, чем loop/recur, а for всегда возвращает последовательность (не набор или карту).

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

обратите внимание, что (для ..) здесь используется только для создания последовательности, содержащей всезначения для компиляции в единый результат set .Или, например:

(reduce + 0 (range 100))
=> 4950
0 голосов
/ 30 сентября 2011

Я думаю, что вы также можете использовать некоторую временную структуру данных в этом сценарии.

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

Просто пример кода, не проверенный.

0 голосов
/ 29 сентября 2011

clojure имеет несколько отличных систем для управления изменяемым состоянием. в этом случае вы можете захотеть атом , содержащий набор

ваши другие варианты:

  • a ref , если необходимо сделать более одного изменения (согласовано много потоков)
  • a var , если это будет однопоточный (переменная может работать здесь так же хорошо, как и атом)
  • агент , если вы хотите установить значение s асинхронно

конечно for возвращает последовательность уже, так что вы можете просто захотеть

 (into #{} (for [ i (range 10)
                  j (range 10) ]
             [i j]))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...