2013-07-28 1 views
3

В ракетке руководстве о parameterize, есть следующий фрагмент кода:Какова последовательность оценок, касающихся `параметризации 'и` let' в Racket?

(define location (make-parameter "here")) 

(let ([get (parameterize ([location "with a fox"]) 
      (lambda() (location)))]) 
    (get)) 

код возвращает "here".

Какая последовательность оценок для этого фрагмента кода? Спасибо.

ответ

5

Это распространенная проблема с динамическими значениями на многих языках (а не только в Racket). Вот что происходит, когда вы оцениваете код:

  1. Параметр location определяется со значением "here"
  2. Введите let ...
  3. Введите parameterize ...
  4. Параметр location динамически обновляется значение "with a fox"
  5. Выражение выражения lambda оценивается для создания замыкания, которое закрывается над location
  6. Возвращение из parameterized блоков-параметра location возвращается к своему исходному значению "here"
  7. Полученный lambda обязан get
  8. Оценки let тела ...
  9. Вы называете (get), и он смотрит на текущее значение location, что составляет "here", и это результат.

Если вы внимательно прочитали документацию по параметрам, это объясняет, что параметр всегда принимает значение ближайшего обновления в стеке. Поскольку ваше обновление со значением "with a fox" выскочит со стека перед тем, как войти в корпус let, оно больше не отображается, когда вы делаете фактический звонок get. Простое исправление, чтобы скопировать значение из параметра и пусть замыкание близко над копией:

(define location (make-parameter "here")) 

(let ([get (parameterize ([location "with a fox"]) 
      (let ([loc (location)]) 
       (lambda() loc)))]) 
    (get)) 

Теперь lambda закрывает над loc, который должен иметь ожидаемое значение.