lazy sequences in dynamic environments

10 views
Skip to first unread message

Stuart Sierra

unread,
Aug 12, 2008, 11:23:13 AM8/12/08
to Clojure
Hello list,

Recent threads and my own experiences have gotten me to thinking: How
should a lazy sequence behave in the presence of dynamic bindings? I
have (mistakenly) written this:

(binding [*some-var* (some temporary value)]
(map my-function a-list))

Where my-function uses the dynamic value of *some-var*. Of course,
this doesn't work as I intend, because map returns a lazy sequence and
control exits the binding form before the rest of the sequence is
evaluated.

Is there a good way around this problem? I can wrap the map in a
doall, but then I lose the advantages of lazy sequences. The only
alternative I can think of is to make my-function take *some-var* as
an argument and then close over it:

(map (partial my-function (some temporary value))
my-list)

But what if the use of *some-var* is buried several calls below my-
function? Arguably, this is just bad design, but it's happened to me
often enough that I wonder if lazy sequences should close over their
dynamic environment the way fns close over their lexical environment.
Is that even possible? What would be the down side?

Curiously,
-Stuart

Rich Hickey

unread,
Aug 12, 2008, 11:48:33 AM8/12/08
to Clojure


On Aug 12, 11:23 am, Stuart Sierra <the.stuart.sie...@gmail.com>
wrote:
Closing over the dynamic environment is kind of a contradiction, and
could cause a lot of confusion. Capturing and re-establishing in every
lazy seq, whether needed or not, would be very expensive.

But you can selectively establish any bindings you want - try this:

(map
#(binding [*some-var* (some temporary value)]
(my-function %))
a-list)

Rich

Stuart Sierra

unread,
Aug 12, 2008, 12:49:05 PM8/12/08
to Clojure
On Aug 12, 11:48 am, Rich Hickey <richhic...@gmail.com> wrote:
> Closing over the dynamic environment is kind of a contradiction, and
> could cause a lot of confusion. Capturing and re-establishing in every
> lazy seq, whether needed or not, would be very expensive.
>
> But you can selectively establish any bindings you want - try this:
>
> (map
>  #(binding [*some-var* (some temporary value)]
>     (my-function %))
>  a-list)

Cool, I hadn't thought of that. Thanks, Rich!

-Stuart
Reply all
Reply to author
Forward
0 new messages