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 -~----------~----~----~----~------~----~------~--~---