2011-09-29 10 views
7

Este me ha estado molestando por un tiempo, ¿Cómo debemos almacenar un valor en un conjunto o mapa en un ciclo for?clojure for loop, almacena los valores en un conjunto o mapa

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

Sé que esto no va a funcionar, pero quiero una funcionalidad similar a este, donde el conjunto contendrá finalmente [0 0] [0 1] ... [0 9] [1 0] .. . [9 9]

Gracias

+0

Gracias a todos, por las respuestas. – KaKa

Respuesta

13

Si entiendo bien su pregunta que usted necesita para convertir su expresión dentro a fuera:

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

Lo que hay que darse cuenta de que aquí es que for devuelve un valor (una secuencia diferida) a diferencia de for-loops en lenguajes más imperativos como Java y C.

0

clojure tiene un varios grandes sistemas para la gestión del estado mutable. en este caso, es posible que desee un atom que contiene un conjunto

sus otras opciones son:

  • un ref si más de un cambio necesita hecho (coordinadas muchos hilos)
  • un var si esto será solo hilo (una var puede funcionar igual de bien aquí como un átomo)
  • un agent si desea establecer el valor de s asíncrona

por supuesto for devuelve una secuencia ya por lo que sólo puede desear

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

El primer fragmento de código aquí no tiene ningún sentido, por lo que puedo decir? No es una forma válida de usar 'swap!', Y como luego mencionarás, no es una buena idea de todos modos. – amalloy

+0

el primer snipit no era realmente el objetivo de la respuesta, así que lo eliminé. posando sin pruebas * tisk tisk * –

6

¿Esto es lo que quieres?

(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]... 

Y si lo que desea la lista como un conjunto:

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

que va a terminar con un conjunto de pares.

5

Generalmente cuando se quiere devolver un conjunto o un mapa u otro 'valor único' que no es un ss de una operación de 'repite' generalizada en un ss, utilizando reduce es más idiomático/sencillo que loop/recur, y for siempre devuelve un seq (no un conjunto o mapa).

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

nota de que (por ..) aquí sólo se usa para producir un ss contiene todos los valores a compilar en el resultado individual conjunto. O, por ejemplo:

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

Creo que también puede usar alguna estructura de datos transitorios en este escenario.

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

Sólo un ejemplo de código, no evaluados.

+1

Esto no es correcto. Desde [los documentos para transitorios] (http://clojure.org/transients): "Tenga en cuenta en particular que los transitorios no están diseñados para ser golpeados in situ. Debe capturar y usar el valor de retorno en la próxima llamada. De esta manera, admiten la misma estructura de código que el código persistente funcional que reemplazan ". – Jonas