This is the mail archive of the guile@cygnus.com mailing list for the guile project.
| Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
|---|---|---|
| Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Jost Boekemeier <jostobfe@calvados.zrz.TU-Berlin.DE> writes:
> is it possible to get and change the environment of a given closure?
In general, no.
It might be possible by changing the module that a closure belongs to,
and thereby affecting its top-level bindings, but I do not recommend
that in any case.
> The function
>
> (define f (lambda (arg) (display arg) (display x) (display y) )
>
> has an environment, which is an obarray with one entry: "arg".
More precisely, the environment includes *all* bindings that are
lexically visible at the point of the lambda. This includes all
bindings made outside the lambde, including all top-level bindings
("f", for example). It does *not* include "arg", which is a free
variable inside the lambda. Each time you invoke f, a new binding for
"arg" is made, and a new environment is constructed by extending the
environment of "f" with this new binding.
Now, there must also exist bindings for "x" and "y" in the environment
for f (everything else would lead to an error). Say they are at the
top-level:
(define x #f)
(define y #f)
(define f (lambda (arg) (display arg) (display x) (display y)))
In Scheme, you can't change the environment of a closure, so "x" and
"y" in the body of f will always refer to the bindings introduced by
the two defines for "x" and "y". You can only change the *values*
that these bindings have while calling f. You want to do this only
temporarily, so that "x" and "y" revert to their old values after f
has returned. This is what `fluid-let' is intended to do. So
(define b
(lambda (arg)
(fluid-let ((x 1)
(y 2))
(f arg))))
This expands into something like
(define b
(lambda (arg)
(let ((old-x 1)
(old-y 2))
(let ((swapper (lambda () (swap x old-x) (swap y old-y))))
(dynamic-wind
swapper
(lambda () (f arg))
swapper)))))
with
(define-macro (swap a b)
(let ((t (gensym)))
`(let ((,t ,a))
(set! ,a ,b)
(set! ,b ,t))))
See the other thread about `fluid-let'.