2012-09-21 4 views
1

Функция теста, как показано ниже:Почему не освобождается локальная переменная?

(defun fab (n) 
    (let ((res '(1 1))) 
     (loop for i from 2 to n do 
      (nconc res (list (+ (nth (- i 2) res) (nth (- i 1) res))))) 
     res)) 

$ ЭСЛ

... EECL (Встраиваемый Common-Lisp) 12.7.1 (мерзавец: UNKNOWN)

...

>(fab 10) 
(1 1 2 3 5 8 13 21 34 55 89) 
>(fab 20) 
(1 1 2 3 5 8 13 21 34 55 89 2 3 5 8 13 21 34 55 89 144 91 5 8 13 21 34 55 89 144 

Тогда я перезапустить ECL

>(fab 20) 
(1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946) 

Кажется, что «res» не освобождается после (fac 10)?

С уважением!

ответ

4

Вы должны использовать (list 1 1), а не '(1 1) в форме let. В Common Lisp эффекты изменения литерала не определены.

(defun fib (n) 
    (let ((res (list 1 1))) ; (list 1 1) instead of '(1 1) 
    (loop for i from 2 to n 
      do (nconc res (list (+ (nth (- i 2) res) (nth (- i 1) res))))) 
    res)) 
1

Константы, такие как '(1 1), выделяются один раз компилятором/интерпретатором. Ваш код использует NCONC в этом списке, изменение и последующие вызовы больше не видят список констант '(1 1), а измененный. В Common Lisp неуказано, что происходит, когда деструктивно изменяет постоянные выражения, а некоторые реализации даже защищают их от изменений, чтобы избежать таких неожиданностей. Если вам нужна новая новая константа, сделайте так, как сказали люди и используйте (список 1 1), или вообще не используйте NCONC.

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