Clojure pin binding reset in for loop

I am new to Clojure and I am trying to redirect the output to a file by linking *out*

. In a simple case, it works nicely:

(binding [*out* (new java.io.FileWriter "test.txt")]
  (println "Hi"))

      

This does what I expect by typing "Hello" to the test.txt file. However, if I introduce a loop for

, things are overkill:

(binding [*out* (new java.io.FileWriter "test.txt")]
  (for [x [1 2]]
    (println "Hi" x)))

      

This time, all output is printed to stdout and the file is empty. What's going on here?

I'm using Leiningen if it matters:

Leiningen 2.0.0 on Java 1.7.0_13 Java HotSpot(TM) 64-Bit Server VM

      

+3


source to share


1 answer


you were bitten by a lazy mistake.

put a doall

or dorun

around the string and inside the anchor

(binding [*out* (new java.io.FileWriter "test.txt")]
  (doall (for [x [1 2]]
           (println "Hi" x))))

      

In your example, printing happens, then the result is printed after it is returned from the binding. Therefore, the binding is no longer in place during printing.

Nothing is printed because the result is a lazy sequence that will later be evaluated when used

user> (def result (binding [*out* (new java.io.FileWriter "test.txt")]
        (for [x [1 2]] 
          (println "Hi" x))))
#'user/result

      



When the replica prints the resulting printlns data:

user> result
(Hi 1
Hi 2 
nil nil) 

      

If we force evaluation of the lazy sequence returned for

inside the binding, nothing is printed in repl,

user> (def result (binding [*out* (new java.io.FileWriter "test.txt")]
  (doall (for [x [1 2]]             
          (println "Hi" x))))) 
#'user/result 
user> result
(nil nil) 

      

and instead the output ends up in a file:

arthur@a:~/hello$ cat test.txt 
Hi 1
Hi 2

      

+5


source







All Articles