Переменная, определенная внутри процедуры, сохраняется?

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

(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)

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

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

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

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

1 ответ

Решение

Пожалуйста, посмотрите на 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) как константа, и этот список выделяется только один раз, независимо от того, сколько раз он вызывается.

Другие вопросы по тегам