Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

repeatedly vs. binding

(def ^:dynamic *d* 1)

(binding [*d* 2]
  (println *d*)
  (repeatedly 1 #(println *d*)))

Output:

2
1

Why? Why does the function inside the repeatedly see the value of the dynamic var from outside the binding?

By the way, I checked (.getId (java.lang.Thread/currentThread)) inside and outside the anonymous function: it's the same.

like image 916
Ben Kovitz Avatar asked Jan 02 '23 21:01

Ben Kovitz


1 Answers

The lazy sequence created by repeatedly is returned from the form, and then realized only when printed via the REPL, after the binding has been "unwound," and it is at this point that the anonymous function is being called. To see that this is the case, try these two variations:

(binding [*d* 2]
  (println *d*)
  (let [x (repeatedly 1 #(println *d*))]
    (println (realized? x))
    x))

and

(binding [*d* 2]
  (println *d*)
  (doall (repeatedly 1 #(println *d*))))

The second variation forces the sequence to be fully realized while still within the scope of the binding.

Note that another way to force the issue is to "capture" the binding by using bound-fn:

(binding [*d* 2]
  (println *d*)
  (repeatedly 1 (bound-fn [] (println *d*)))) 
like image 82
Mike Fikes Avatar answered Jan 14 '23 15:01

Mike Fikes