Reputation: 3922
In The Racket Guide about parameterize, there's the following piece of code:
(define location (make-parameter "here"))
(let ([get (parameterize ([location "with a fox"])
(lambda () (location)))])
(get))
The code returns "here"
.
What's the sequence of evaluating this piece of code? Thank you.
Upvotes: 3
Views: 141
Reputation: 33019
This is a common problem with dynamically-scoped values in many languages (not just Racket). Here's what happens when you evaluate the code:
location
parameter is defined with value "here"
let
...parameterize
...location
is dynamically updated with the value "with a fox"
lambda
expression is evaluated to create a closure which closes over location
parameterized
block—parameter location
reverts to its original value of "here"
lambda
is bound to get
let
body...(get)
, and it looks up the current value of location
, which is "here"
, and that's the result.If you carefully read the documentation on parameters it explains that the parameter always takes the value of the closest update in the stack. Since your update with the value "with a fox"
gets popped off the stack before going into the let
body, it's no longer visible when you make the actual call to get
. A simple fix is to copy the value from the parameter and let the closure close over the copy:
(define location (make-parameter "here"))
(let ([get (parameterize ([location "with a fox"])
(let ([loc (location)])
(lambda () loc)))])
(get))
Now the lambda
closes over loc
, which should have the expected value.
Upvotes: 4