Home > Archive > Scheme > March 2007 > fluid binding
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
|
|
| Marlene Miller 2007-03-03, 10:07 pm |
| Does a fluid binding override the binding in a closure?
(let ((x 4))
(let ((p (lambda (y) (+ x y))))
(+ (fluid-let ((x 7)) (p 1)) (p 2))))
;=> 14
(let ((x 0))
((lambda (p) (+ (fluid-let ((x 7)) (p 1)) (p 2)))
(let ((x 4)) (lambda (y) (+ x y)))))
;=> 11
- - - - - - - - - -
"Some Scheme implementations support a controlled form of assignment known
as fluid binding, in which a variable takes on a temporary value during a
given computation and reverts to the old value after the computation has
completed. The syntactic form fluid-let defined below in terms of
dynamic-wind permits the fluid binding of a single variable x to a value v
within a sequence of expressions e1 e2 .... "
(define-syntax fluid-let
(syntax-rules ()
((_ ((x v)) e1 e2 ...)
(let ((y v))
(let ((swap (lambda () (let ((t x)) (set! x y) (set! y t)))))
(dynamic-wind swap (lambda () e1 e2 ...) swap))))))
http://www.scheme.com/tspl3/control.html
- - - - - - - - - -
"We suggested earlier the use of assignment to make a program more modular
by allowing one procedure to communicate information to a distant procedure
without requiring intermediate procedures to be aware of it. Very often such
an assignment should only be temporary, lasting for the execution of a
procedure call." [...] setdynamic-exp (id rhs-exp body) "The effect of the
setdynamic expression is to assign temporarily the value of rhs-exp to id,
evaluate body, re-assign original value, and return the value of body."
EOPL Exercise 3.47 page 106-107
| |
| Max Hailperin 2007-03-04, 7:09 pm |
| "Marlene Miller" <marlenemiller@worldnet.att.net> writes:
> Does a fluid binding override the binding in a closure?
>
> (let ((x 4))
> (let ((p (lambda (y) (+ x y))))
> (+ (fluid-let ((x 7)) (p 1)) (p 2))))
> ;=> 14
>
> (let ((x 0))
> ((lambda (p) (+ (fluid-let ((x 7)) (p 1)) (p 2)))
> (let ((x 4)) (lambda (y) (+ x y)))))
> ;=> 11
[relevant quotes from TSPL and EOPL deleted]
This comes back to the distinction we previously discussed between the
environment, which maps names to storage locations, and the store,
which maps storage locations to values. The fluid-let construct
affects only the store, changing the contents of a location rather
than the name-to-location binding. Because closures retain the
environment's binding of names to storage locations, not the contents
of the store, this means there is nothing for the fluid-let to
override.
The remaining paragraphs spell this out in more detail, primarily for
anyone else listening in -- I suspect the first paragraph was enough
for you, Marlene.
The fluid-let construct is a close relative of set!. As with set!, it
does not affect the correspondence between names and storage locations
(as the evaluation of let does, or as the application of a procedure
created with lambda does). Instead, it changes what value is stored
in the storage location.
In your first example above, there is exactly one storage location
named x. That location starts out holding 4, is changed to hold 7,
and then is changed to hold 4 again. Because the lambda expression is
within the scope of the let that establishes the binding of x to that
storage location, this is the binding that the closure retains.
Whenever the procedure is applied, the current contents of the storage
location is added to the procedure's argument. When the procedure is
applied to 1, the storage location holds 7, and so 8 is produced.
When the procedure is aplied to 2, the storage location holds 4, and
so 6 is produced. The value of 14 you show is the sum of 8 and 6.
In the second example, there are two different storage locations named
x, each established by a let expression. The outer let establishes a
storage location that intially holds 0, is temporarily changed to hold
7, and then is changed to hold 0 again. The inner let establishes a
storage location that holds 4 throughout its entire lifetime. The two
variables named x, each with a statically identifiable scope, could be
made explicit by giving them different names:
(let ((x0 0))
((lambda (p) (+ (fluid-let ((x0 7)) (p 1)) (p 2)))
(let ((x1 4)) (lambda (y) (+ x1 y)))))
;=> 11
Note in particular that no use is being made of the location named
x0. Its value is set from 0 to 7 and back to 0, but not used
anywhere. The value added to 1 and 2 is the value of x1, namely 4.
These additions produce 5 and 6, whose sum of 11 is shown.
| |
| Marlene Miller 2007-03-04, 10:10 pm |
| "Max Hailperin" wrote in message:.
> "Marlene Miller"writes:
>
>
> [relevant quotes from TSPL and EOPL deleted]
>
> This comes back to the distinction we previously discussed between the
> environment, which maps names to storage locations, and the store,
> which maps storage locations to values. The fluid-let construct
> affects only the store, changing the contents of a location rather
> than the name-to-location binding. Because closures retain the
> environment's binding of names to storage locations, not the contents
> of the store, this means there is nothing for the fluid-let to
> override.
Ok. I think it should be called fluid-set!
>[...]
>
> The fluid-let construct is a close relative of set!. As with set!, it
> does not affect the correspondence between names and storage locations
> (as the evaluation of let does, or as the application of a procedure
> created with lambda does). Instead, it changes what value is stored
> in the storage location.
>
>[...]
| |
| Marlene Miller 2007-03-05, 8:15 am |
| "Max Hailperin" wrote...
> "Marlene Miller" <marlenemiller@worldnet.att.net> writes:
>
>
> [relevant quotes from TSPL and EOPL deleted]
>
> This comes back to the distinction we previously discussed between the
> environment, which maps names to storage locations, and the store,
> which maps storage locations to values. The fluid-let construct
> affects only the store, changing the contents of a location rather
> than the name-to-location binding. Because closures retain the
> environment's binding of names to storage locations, not the contents
> of the store, this means there is nothing for the fluid-let to
> override.
>[...]
Here is an interesting discussion (in 1999) which touches on the semantics
of fluid-let in Scheme48, Gambit and Kawa and the issue of threads in the
implementation. http://srfi.schemers.org/srfi-15/ma...e/maillist.html
Notice they talk about dynamic scope and dynamic binding.
For example, extracting a few pieces
- - - - - - - - - -
http://srfi.schemers.org/srfi-15/ma...e/msg00001.html
(MAKE-FLUID value) -> fluid
(LET-FLUID fluid value thunk)
(LET-FLUIDS fluid1 value1 ... fluidn valuen thunk)
(FLUID fluid) -> value
(SET-FLUID! fluid value)
Fluid values are cells that have dynamic scope, as provided by LET-FLUID.
- - - - - - - - - -
http://srfi.schemers.org/srfi-15/ma...e/msg00002.html
In particular, I don't like having to have variables with dynamic scope
visible lexically in the context where
they're used.
@deffn {special form} dynamic-define @var{var} @var{val}
@deffnx {special form} dynamic-ref @var{var}
@deffnx {special form} dynamic-set! @var{var} @var{val}
@deffnx {special form} dynamic-let ((@var{var} @var{val})@dots{}) @var{body}
@cindex dynamic scoping
@cindex dynamic variables
@cindex variables, dynamic
These special forms provide support for ``dynamic variables'' which have
dynamic scope.
- - - - - - - - - -
http://srfi.schemers.org/srfi-15/ma...e/msg00003.html
When a non-local variable is evaluated, the evaluator searches the current
thread's fluid binding list, and finds the first binding for the given name.
If none, is found, the global binding is returned.
- - - - - - - - - -
http://srfi.schemers.org/srfi-15/ma...e/msg00007.html
The important point is handling the interaction between threads and dynamic
binding.
This model that you, Brad, and I are pushing allows threads to share and not
share dynamic scope,
| |
| Marlene Miller 2007-03-06, 4:26 am |
| "Marlene Miller" wrote... about variations on fluid-let in various Scheme
implementations.
Let's ignore my above post. I don't need to know about fluid-let at that
level of detail.
| |
| Wolfram Fenske 2007-03-06, 7:07 pm |
| "Marlene Miller" <marlenemiller@worldnet.att.net> writes:
[...]
> Here is an interesting discussion (in 1999) which touches on the semantics
> of fluid-let in Scheme48, Gambit and Kawa and the issue of threads in the
> implementation. http://srfi.schemers.org/srfi-15/ma...e/maillist.html
> Notice they talk about dynamic scope and dynamic binding.
[...]
> These special forms provide support for ``dynamic variables'' which have
> dynamic scope.
I don't have time to read these SRFI's but you might want to have a
look at Common Lisp's dynamic (a.k.a "special") variables, in case you
don't know about them already. Peter Seibel's "Practical Common Lisp"
has a section about them in the chapter on variables:
<http://www.gigamonkeys.com/book/variables.html>
Dynamic variables work almost like "fluid-let", but not quite. ISLISP
[1] has them, too, but in contrast to Common Lisp, it introduces
additional syntax to rebind, set, and read them. This makes it clear
whether you deal with dynamic variables or lexical variables. In
Common Lisp, OTOH, you can't tell whether
(let ((x "outer"))
(funcall (let ((x "inner"))
(lambda () x))))
returns "outer" or "inner". Here's what Clisp does:
--8<---------------cut here---------------start------------->8---
[1]> (let ((x "outer")) ; lexical binding is the default in CL
(funcall (let ((x "inner"))
(lambda () x))))
"inner"
[2]> (defparameter x "foo") ; define x as a dynamic variable
X
[3]> (let ((x "outer")) ; since "x" is now a dynamic variable, dynamic
; binding is used
(funcall (let ((x "inner"))
(lambda () x)))) ; this closure does not capture x's
; new binding
"outer"
[4]>
--8<---------------cut here---------------end--------------->8---
That's why it's good style in Common Lisp to give dynamic variables
names that start and end with a "*". This way you *can* tell what's
what.
Footnotes:
[1] A draft of the specification can be found here:
<http://islisp.info/v20a-pd-islisp.pdf>
Regards
--
Wolfram Fenske
A: Yes.[color=darkred]
>Q: Are you sure?
|
|
|
|
|