문제

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.

도움이 되었습니까?

해결책

This is a common problem with dynamically-scoped values in many languages (not just Racket). Here's what happens when you evaluate the code:

  1. The location parameter is defined with value "here"
  2. Enter the let...
  3. Enter parameterize...
  4. The parameter location is dynamically updated with the value "with a fox"
  5. The lambda expression is evaluated to create a closure which closes over location
  6. Return from parameterized block—parameter location reverts to its original value of "here"
  7. The resulting lambda is bound to get
  8. Evaluate let body...
  9. You call (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.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top