10.3.2 Parameters
Dynamic Binding: parameterize in Guide: Racket introduces parameters.
See Parameters for basic information on the parameter model. Parameters correspond to preserved thread fluids in Scsh [Gasbichler02].
To parameterize code in a thread- and continuation-friendly manner, use parameterize. The parameterize form introduces a fresh thread cell for the dynamic extent of its body expressions.
When a new thread is created, the parameterization for the new thread’s initial continuation is the parameterization of the creator thread. Since each parameter’s thread cell is preserved, the new thread “inherits” the parameter values of its creating thread. When a continuation is moved from one thread to another, settings introduced with parameterize effectively move with the continuation.
In contrast, direct assignment to a parameter (by calling the parameter procedure with a value) changes the value in a thread cell, and therefore changes the setting only for the current thread. Consequently, as far as the memory manager is concerned, the value originally associated with a parameter through parameterize remains reachable as long the continuation is reachable, even if the parameter is mutated.
(make-parameter v [guard]) → parameter? |
v : any/c |
guard : (or/c (any/c . -> . any) #f) = #f |
| ||||||
|
Dynamic Binding: parameterize in Guide: Racket introduces parameterize.
The result of a parameterize expression is the result of the last body. The parameter-exprs determine the parameters to set, and the value-exprs determine the corresponding values to install while evaluating the body-exprs. All of the parameter-exprs are evaluated first (and checked with parameter?), then all value-exprs are evaluated, and then the parameters are bound in the continuation to preserved thread cells that contain the values of the value-exprs. The last body-expr is in tail position with respect to the entire parameterize form.
Outside the dynamic extent of a parameterize expression, parameters remain bound to other thread cells. Effectively, therefore, old parameters settings are restored as control exits the parameterize expression.
If a continuation is captured during the evaluation of parameterize, invoking the continuation effectively re-introduces the parameterization, since a parameterization is associated to a continuation via a continuation mark (see Continuation Marks) using a private key.
Examples: | |||||||||
| |||||||||
> (define p1 (make-parameter 1)) | |||||||||
> (define p2 (make-parameter 2)) | |||||||||
| |||||||||
'(3 . 1) | |||||||||
| |||||||||
'(1 . 3) | |||||||||
> (define ch (make-channel)) | |||||||||
| |||||||||
#<thread> | |||||||||
> (channel-get ch) | |||||||||
'(0 . 2) | |||||||||
> (define k-ch (make-channel)) | |||||||||
| |||||||||
> (send-k) | |||||||||
#<thread> | |||||||||
| |||||||||
#<thread> | |||||||||
> (channel-get ch) | |||||||||
1 | |||||||||
> (send-k) | |||||||||
#<thread> | |||||||||
> (thread (lambda () ((channel-get k-ch) p1))) | |||||||||
#<thread> | |||||||||
> (channel-get ch) | |||||||||
0 |
|
| |||||||||||||||||||||
parameter : parameter? | |||||||||||||||||||||
guard : (any/c . -> . any) | |||||||||||||||||||||
wrap : (any/c . -> . any) |
guard applied when setting the parameter (before any guard associated with parameter), and
wrap applied when obtaining the parameter’s value.
See also chaperone-procedure, which can also be used to guard parameter procedures.
(parameter? v) → boolean? |
v : any/c |
(parameter-procedure=? a b) → boolean? |
a : parameter? |
b : parameter? |
| ||||||||||||||
parameterization : parameterization? | ||||||||||||||
thunk : (-> any) |
(parameterization? v) → boolean? |
v : any/c |