On Thu, Oct 1, 2009 at 12:03 PM, jon <superuser...@googlemail.com> wrote:
>
> On Sep 29, 10:31 pm, Rich Hickey <richhic...@gmail.com> wrote:
>> On Tue, Sep 29, 2009 at 4:04 PM, jon <superuser...@googlemail.com> wrote:
>>
>> 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.
>
> Hi Rich,
>
> (Note - when I say 'environment' below I'm referring to one specially
> designated 'environment Var', not the whole set of dynamically bound
> Vars we are used to.)
>
> I'm not sure whether you are taking into account the fact that the
> semantics of my proposal are that each (fn ..) will only capture (and
> later rebind) the environment if it is non-nil at the point it is
> instantiated (in the java sense). The environment's root-binding is
> nil, and all the user's code should be loaded in this state so that
> the (defn ..)s themselves don't capture anything.. ie.no capturing
> happens until the user code explicitly 'switches it on' with a (with-
> env ..) and then only newly instantiated (fn ..)s will capture the
> current environment.
>
> For those kinds of environment data that don't require the fully
> dynamic behavior of the regular Vars, wouldn't this be more intuitive
> default behavior (ie.that all code "kicked-off" under a given
> environment should be evaluated under that environment, even if that
> happens later on) rather than the current situation in which any
> eagerly evaluated code would see the current environment, and any
> delayed-evaluation code would see 'whatever it happens to be at the
> time', which would be harder to control?
> For the (presumably rare) case that some library code (which may be
> called under a non-nil environment) needs to create a (fn ..utilizing
> *env*..) which is to be passed out and executed under some yet-to-be-
> determined environment.. it could simply be wrapped like this:
>  (with-env nil (fn ..utilizing *env*..))
>
> -----
> The example you gave doesn't behave badly (ie.differently) when
> replacing the body of foo for its call.. as demonstrated below.
>
> user=> (defn send-off-something-that-uses-env [f] (+ 100 (f)))
> #'user/send-off-something-that-uses-env
> user=> (defn foo [] (send-off-something-that-uses-env (fn [] (+ 10
> *env*))))
> #'user/foo
> user=> (defn bar [] (with-env 1 (foo)))
> #'user/bar
> user=> (bar)
> 111
> user=> (defn bar [] (with-env 1 (send-off-something-that-uses-env (fn
> [] (+ 10 *env*)))))
> #'user/bar
> user=> (bar)
> 111
>
> Could you elaborate a bit more on the bad behavior you see..?

It simply doesn't compose or flow. Making the nil env special (e.g.
non-replacing) just moves the problem into higher-order functions that
use the construct:

(defn needs-x []
  (use-env-x))

(defn needs-y []
  (use-env-y))

(defn foo []
  (with-env x (fn [f] (needs-x) (f))))

(let [f (foo)]
  (with-env y (f needs-y)))

needs-y isn't going to get it.

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