Hi, Am 01.10.2009 um 19:08 schrieb Rich Hickey:
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.
This is "simply" solved by having a chain of environments. The algorithm works like this:
* The desired value is contained in the current map. => Use it. ("Younger" bindings override "older" ones) * The desired value is not contained go up one step in the chain of env maps and repeat. * If there is no further step in the chain (ie. we arrived at nil), use the root binding of the Var.
"simply" with quotes, because I have no clue about the performance impact of that. It should fix your example, though.
Elk, an rather old, embeddable Scheme interpreter, constructs its environment like that.
Sincerely Meikel
smime.p7s
Description: S/MIME cryptographic signature