测试功能如下:
(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))
$ecl
EECL(嵌入式公共Lisp)12.7.1(git: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)之后没有被释放?
真诚!
在let
形式中应该使用(list 1 1)
而不是'(1 1)
。在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)。您的代码在此列表中使用NCONC,修改后,后续调用将不再看到常量列表"(11)",而是修改后的列表。在Common Lisp中,未指定当打开时破坏性地修改常量表达式时会发生什么,有些实现甚至保护它们不受更改的影响,以避免此类意外。如果你需要一个新的常数,按照人们说的去做并使用(列表1 1),或者完全避免使用NCONC。