2013-08-27 2 views
2

Я искал какое-то время, и я не могу найти правильный вопрос, поэтому отправлю его. Надеюсь, что это уже не отправлено.СХЕМА: Почему «установлен!» изменить локальную переменную 'let'?

Я понимаю, что комплект! и let делаю, но непонятно почему комплект! может изменять локальную переменную let и сохранять значение навсегда. Например:

(define count 
    (let ((cont 0)) 
    (lambda() 
     (set! cont (+ cont 1)) 
     cont))) 

Если оценивать (количество) несколько раз мы видим, что результат

> (count) 
1 
> (count) 
2 
> (count) 
3 
> 

... и так далее. Но, насколько я понимаю, cont - это локальная переменная, поэтому почему она сохраняет значение? Почему он не установлен в 0 при каждом вызове функции?

Ну, это :) Заранее спасибо!

PS: Извините мой английский * о *

ответ

5

Это происходит потому, что count создает closure, что «магазины» значение cont, и он будет помнить ее значение даже между вызовами процедуры. Обратите внимание, что lambda присваивается count имя после, определяющее cont как переменную, и при этом lambda закрывается над cont. Это уже не local переменная, ее переменная, которая определена вне процедуры и разделяется между всеми ее вызовами, «запоминая» значение, которое оно имело в последнем вызове.

Для сравнения, посмотрите, как выглядит процедура с действительно локальными переменными:

(define count 
    (lambda() 
    (let ((cont 0)) 
     (set! cont (+ cont 1)) 
     cont))) 

выше будет всегда возвращение 1, сравнить его с процедурой, описанной в вопросе.

+0

О, я вижу. Спасибо за ответ! :) – Warren

+0

Выполняет ли каждая процедура, которая определяет переменную, одинаково? (запоминание значения переменной) – Warren

+0

@ ee7 no, только те, которые определяют переменные _before_ 'lambda'. Посмотрите на мой отредактированный ответ, есть пример действительно локальной переменной, которая не будет «запоминаться» между вызовами. Вы должны понять концепцию закрытия, чтобы понять, почему это работает. –