I'm trying to create a for in Clojure.
I'm following the cheats sheet from the Clojure site.
e.g:
(take 100 (for [x (range 100000000) y (range 1000000) :while (< y x)] [x y]))
I'm trying to create my own for
which should print "Hello World" 100 times.
(take 100 (for [a (range 100)
:while (< a 100)]
(println "Hello World")
)
)
For some reason it's not printing Hello World 100 times. Why not?
The most important thing you need to be aware of, is that sequences in Clojure are lazy. That means the items in the sequence are only evaluated when they are needed. This allows you to work with infinite sequences.
Most of the time this is what you want, but it can be confusing when you are not really interested in the values of the sequence items, but in the side-effects of the functions that create the sequence items. In your example, the sequence is made up of 100 return values of the println
function, that is 100 times nil
- not very interesting. But the println
function has the side-effect of printing "Hello World" to stdout.
The problem is, if you never do anything with the items in the sequence, the println
functions are never evaluated and the strings are not printed. It kinda works in the REPL, because the P in REPL stands for print - the return value of the expression you typed in is printed. To print the whole sequence, it must be evaluated, so you see a bunch of "Hello World"s, but also a bunch of nils
. If you run the code outside of the REPL (without using the returned value), you won't see the Hello Worlds.
If you're interested in the side-effects of your item-generating functions, you can use doall
or doseq
. doall
forces the whole sequence to be evaluated and returns it:
(doall (for [a (range 100)] (println "Hello World")))
doseq
doesn't return the sequence (it returns nil
) and has a syntax like for
:
(doseq [a (range 100)] (println "Hello World"))
Also note that you really only need to supply the desired count (100) once. The range
function already produces a sequence with 100 items in it. The :while
clause in your code is redundant, as is the take
function (taking the first 100 items from a sequence with 100 items doesn't do much).
Hope this helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With