Skip to end of metadata
Go to start of metadata

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:
  1. Aug 28, 2011

    What you're seeing is the output of the value, (nil nil), interspersed with the execution of the value - which prints \b on each line.

    Consider this code:

    (let [d (for [i (range 1 3)] (println \b))]
      (println "What is d?")
      (doall d)
      (println "d is...")
      (println d))

    This will print:
    What is d?
    b
    b
    d is...
    (nil nil)
    nil

    Here you can clearly see that \b is printed when d is evaluated - via doall - but when you print d you get a list with two nil values as expected.

  2. Aug 29, 2011

    Hi, Julian,

    This sort of question-and-answer discussion is best on the Clojure mailing list instead of this wiki.

    http://groups.google.com/group/clojure

    Thanks,
    Stuart Sierra
    clojure.com