13

how can I print a list of n, say 10, numbers on 10 lines? I just learned about loop and recur, but cannot seem to combine a side-effect (println i) with (recur (+ i 1)) in a loop form. Just to be very clear: I'd like output like this:

1
2
3
4
5
6
7
8
9
10

when n is 10.

Roger
  • 131
  • 1
  • 3

5 Answers5

16

You can use doseq for this, which is meant to be used when iteration involves side effects,

(doseq [i (range 10)]
   (println i))

You could use map as pointed but that will produce a sequence full of nils which is both not idiomatic and wastes resources also doseq is not lazy so no need to force it with doall.

Hamza Yerlikaya
  • 49,047
  • 44
  • 147
  • 241
11

I suggest dotimes for this kind of simple loop:

(dotimes [i 10]
  (println (inc i)))

Note that dotimes is non-lazy, so it is good for things like println that cause side effects.

mikera
  • 105,238
  • 25
  • 256
  • 415
3

With loop/recur:

(loop [i 1]
  (when (<= i 10)
    (println i)
    (recur (inc i))))

However, it's more idiomatic (read: more "Clojuristic") to map the function println over the numbers in 1..10. But because map returns a lazy sequence, you must force its evaluation with doall:

(doall (map println (range 1 (inc 10))))
Leonel
  • 28,541
  • 26
  • 76
  • 103
  • 4
    In fact it is more idiomatic to use `doseq` (or `dotimes`) in this case, because it is all about side-effects. `map` should only be used if you are interested in the return value. Otherwise you get easily caught by laziness. – kotarak Jun 29 '11 at 14:52
  • So that would be (dotimes [i 10] (println i)) Thanks! Will remember that when I get to chapter 14 in 'Practical Clojure' (now finishing up chapter 3) :-) – Roger Jun 29 '11 at 16:38
0

If you only want to print the output on the screen, you might also simply put a (println i) before entering your conditional:

(loop [i 0]
  (println i)
  (if (< i 10)
    (recur (inc i))
    (println "done!")))

And the output will be one number per line.

josliber
  • 43,891
  • 12
  • 98
  • 133
0

And just to be comprehensive you can do it with map also:

(doseq (map #(println %) (range 10))
Arthur Ulfeldt
  • 90,827
  • 27
  • 201
  • 284