2011-12-16 15 views
11

Soy nuevo en Clojure y he descubierto que cuando cierro este vector en clojure usando una lista de comprensión obtengo unos nil s al final.Looping sobre vectores

(def myVec [1,2,3]) 

user=> (for [x myVec] (println x)) 
(1 
2 
3 
nil nil nil) 

puedo conseguir lo mismo usando map

user=> (map println myVec) 
(1 
2 
3 
nil nil nil) 

lo que causa la nill se va a imprimir en estos casos?

+2

usando (doseq [x myVec] (println x)) – BLUEPIXY

Respuesta

6

Aquellos nil son el valor de retorno de println. Cada vez que se llama

(println "something") 

las impresiones de función printlnsomething en la salida estándar, y luego vuelve nil. El efecto general en su código es que ve todos los efectos secundarios (E/S) de todas las invocaciones de println, luego el REPL imprime el valor de retorno proveniente de cada invocación (por ejemplo, tres veces nil).

9

for y map crear una nueva secuencia perezoso con cada elemento en el vector original reemplazado por el resultado de (println element), y println devuelve nil.

No debe utilizar for y map para realizar efectos secundarios (como la impresión) en los elementos. Use doseq para eso.

+0

Un poco de la confusión proviene del orden en que se imprimen los datos. El paréntesis inicial se imprime como parte de la lista que (map (println ...)) devuelve, luego se obtiene el resultado de cada println, luego los nils que forman parte de la lista de (map (println ...)) . Si cambia a usar doseq, o si (doall (map (println ...))), los resultados serán un poco menos ambiguos ya que verá todas las impresiones antes de obtener los valores de retorno. (dorun (map (println ...))) volverá solo. A menos que obtuviera dorun y doall revertido. –

+4

@ SavanniD'Gerinel Las cosas que dices son vagamente ciertas, pero erróneas en la mayoría de los detalles. Las cosas salen en el orden "incorrecto" porque la secuencia se fragmenta, no porque la réplica imprime efectos secundarios antes de los valores: si tenía una secuencia no escindida como '(tome 10 (itere # (inc (doto% println)) 0)) ', verá valores de retorno intercalados con resultados de impresión. De manera similar, si tuviera una lista más grande que un solo fragmento (por ejemplo, de tamaño 50), obtendría un montón de impresiones, luego un montón de valores, luego más impresiones ... – amalloy

+0

Eso es informativo. La esencia de lo que decía era que no se podía predecir el orden en que se imprimían las cosas, pero incluso eso habría sido impreciso, dado el fragor al que se refiere aquí. Tal como está, solo me di cuenta de la fragmentación hace unos días. –

1

nil es el valor devuelto por println por lo que está viendo las líneas impresas seguidas por la lista asignada de valores nulos.