On Tue, Sep 29, 2009 at 4:04 PM, jon <superuser...@googlemail.com> wrote:
>
> Hi.. long post.. it's a Request For Comment :)
>
> Clojure's "thread local binding facility" for Vars has always seemed
> like
> a useful (but of course misusable) feature to have available in our
> toolbox..
> However it soon becomes apparent that Var bindings don't play nice
> with
> laziness - and since laziness can creep in all over the place
> (eg. using standard sequence functions, direct use of (lazy-seq ..),
>  using (delay ..), perhaps from any (fn ..) you create)
> that renders them of much less value.. almost too unsafe to tangle
> with
> in my opinion.
> To quote Rich, "there is a fundamental tension between laziness and
> dynamic
> scope, combine with extreme caution."
>
> The underlying problem is that when each (fn ..) gets created it
> doesn't
> capture the current dynamic environment so that it can subsequently be
> made
> available when it is eventually invoked.

This is not a 'problem', this is what dynamic means.

> To quote Rich once more, "The overhead for capturing the dynamic
> context
> for every lazy seq op would be extreme, and would effectively render
> dynamics non-dynamic."
>
> To help alleviate the problem somewhat, a (bound-fn ..) helper macro
> has
> been created (https://www.assembla.com/spaces/clojure/tickets/170)
> but my guess is that its use would be impractical/ugly/risky..
> it would need to be used "all over the place" and forgetting to use it
> in any of those places could introduce a bug.
>

I don't think so. There are people who are sending off jobs to agents
that they know will used the dynamic environment for which bound-fn
will work perfectly. And most code need never consider it. If you need
it all over the place you have too much use of dynamic vars and
laziness + side-effects. The person who needs to think about this is
the person using send/future etc with context-sensitive work. If there
were to be generic capturing points, it might be macros wrapping
those.

> I've been thinking about an alternative to (bound-fn ..) and would
> like your opinions on the following tweak to Clojure:
>

> ...Implementation details elided...

> With a better integrated, better designed implementation, I'm
> certain this could be improved further.
> In that case, would this be a worthwhile enhancement to Clojure?
> Seems like it could be a win-win situation, since it rescues
> (semi-)dynamic bindings from the gnashing jaws of laziness
> for those that want to use it, but shouldn't impact negatively
> upon those that don't?
> Or is there something fundamentally wrong with the idea?
>

Before leaping to implementation/performance issues, I think it is
important to think about the semantics of this - what does it mean? I
think you will get a lot of confusion, given:

(defn foo []
        (send-off-something-that-uses-env (fn [] ... (use-env))))
        
(defn bar []
        (establish-env env
                (foo)))

If fns 'capture' these environments when created, and re-establish
them when called, then foo itself will have captured the environment
at *its* definition/creation point, and will re-establish that, thus
the environment setup by bar will not be conveyed through foo to
something-that-uses-env - *but*, if you substituted the body of foo
for its call, it would. That's bad.

Rich

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to