Skip to end of metadata
Go to start of metadata
You are viewing an old version of this page. View the current version. Compare with Current  |   View Page History

Hi All,

I am a Clojure newbie and can't figure out why the following code (1.2.1 or 1.3.0 beta1):

(for [i (range 1 3)] (println \b))
(b
b
nil nil)
user=> (for [i (range 1 3)] (println \b))

Prints this in REPL:

user=> (b

b

nil nil)

Since println is supposed to return nil, I expected (nil, nil) to be returned. In reality, the value(\b) that was supposed to be only printed, is also (apparently) returned in the result collection

Ok, let's take this apart some more:

user=> (def f (for [i (range 1 3)] (println \b)))

user=> f

(b

b

nil nil)

Still surprising - I thought I was defining a variable with value being the result of the for macro execution, but it either executed again when f was evaluated, or the result actually contains printed (not captured) values...

Final experiment:

user=> ((vec f) 0)

nil

user=> ((vec f) 1)

nil

user=> ((vec f) 2)

IndexOutOfBoundsException

Now, this reveals that the result actually was correct all along. It is unclear why REPL decided to make the printed values part of the result. Maybe it started with an open parenthesis too early? E.g. it should have printed

b

b

(nil nil)

If so, this is a minor (but confusing for the unitiated) bug. What was more surprising to me is that evaluating f apparently re-evaluated the for. Is this really so? This is not true in the following case:

user=> (defn f3[] (do (println "call") 1))
user=> (def f (f3))
call
#'user/f
user=> f
1
Here f3 is evaluated once, and not re-evaluated when f is computed. What's the difference from the previous example with for? Am I missing something essential here?

Thanks in advance,
Julian

Labels: