2014-01-24 7 views
1

Я написал процедуру (do-test). Поскольку тест может иметь некоторые эффекты на переменную env, я определила env внутри do-test надеясь, что env не будет осуществляться с процедурой, поэтому каждый раз, когда я запускаю его, я буду получать свежую среду для работы. К моему удивлению, мои тестовые процедуры на самом деле несут предыдущие env. Пожалуйста, найдите follwing код:переменная, определенная внутри процедуры, сохраняется?

(define (do-test) 

    (define env '(1)) 
    ;(define env (list 1)) 

    (display env) 
    (if (not (equal? (car env) 1)) 
    (error "assertion failed.") 
    'ok) 

    (set-car! env 2) 
    'ok) 

(do-test) 
(do-test) 

Я пытался запустить этот код с помощью мит-схемы/лукавства/codepad.org, и все из которых сказал мне подножка (do-test) дважды дали различные результаты.

Но если я изменю линию (define env '(1)) до (define env (list 1)), я получу ожидаемый результат. (Вы можете найти свой код before и after изменение codepad.org)

Насколько мне известно, '(1) и (list 1) должны быть такими же, за исключением того, что второй будет вызов процедуры list.

Мне интересно, почему это происходит и как я могу предотвратить повторное использование программы предыдущими значениями?

ответ

0

Пожалуйста, обратите внимание на R5RS, в котором говорится, что

это ошибка, чтобы изменить постоянную (то есть значение буквального выражения), используя процедуру мутации, как set-car! или string-set!.

Так '(1) и (list 1) не совсем то же самое: когда вы намерены построить некоторые данные, которые будут мутировал в будущем, не используйте цитаты.

Если вы попытаетесь сделать это:

(define (f) (list 1)) 
(define (g) '(1)) 
(display (eq? (f) (f)))(newline) 
(display (eq? (g) (g)))(newline) 

Вы получите:

#f 
#t 

Это предполагает, что f будет составить список каждый раз, когда вызывается. Но g будет обрабатывать свой список '(1) как константу, и этот список выделяется только один раз, независимо от того, сколько раз он вызывается.

Смежные вопросы