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

$ecl

... EECL(嵌入式 Common-Lisp)12.7.1(git:未知)

...

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

似乎在 (fac 10) 之后没有释放“res”?

真挚地!

4

2 回答 2

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))
于 2012-09-21T01:21:24.470 回答
1

'(1 1) 等常量仅由编译器/解释器分配一次。您的代码在此列表中使用 NCONC,进行修改后,后续调用不再看到常量列表 '(1 1),而是看到修改后的列表。在 Common Lisp 中,未指定当对常量表达式进行破坏性修改时会发生什么,并且一些实现甚至保护它们免受更改以避免此类意外。如果您需要一个全新的常量,请按照人们所说的使用(列表 1 1)或完全避免使用 NCONC。

于 2012-09-25T14:19:43.217 回答