Common Lisp中的可变范围

时间:2019-08-11 21:46:43

标签: common-lisp

我有以下Common Lisp代码,并且对counter变量的绑定方式感到困惑。

(defun count-bases (strand)
  (let ((counter (list '(a . 0) '(c . 0) '(g . 0) '(t . 0))))
    (inspect counter)
    (labels ((inc-counter (base)
               (incf (cdr (assoc base counter)))))
      (dolist (element strand (mapcar #'(lambda (pair) (list (car pair) (cdr pair))) counter))
        (cond ((symbolp element) (inc-counter element))
              (t (inc-counter (first element))
                 (inc-counter (second element))))))))

我希望每次调用此函数时,值'((a . 0) (c . 0) (g . 0) (t . 0))都绑定到counter变量,并且在函数完成时counter变量会超出范围。但是,第二次调用函数(如下所示)时,counter变量保留了第一次调用时的值。

CL-USER> (count-bases '(a t t a g c a c))

The object is a proper list of length 4.
0. 0: (A . 0)
1. 1: (C . 0)
2. 2: (G . 0)
3. 3: (T . 0)
> E

((A 3) (C 2) (G 1) (T 2))
CL-USER> (count-bases '(a t t a g c a c))

The object is a proper list of length 4.
0. 0: (A . 3)
1. 1: (C . 2)
2. 2: (G . 1)
3. 3: (T . 2)
> E

((A 6) (C 4) (G 2) (T 4))
CL-USER> 

有人能解释一下每次调用函数时在这里发生了什么以及如何绑定绑定变量吗?非常感谢。

1 个答案:

答案 0 :(得分:4)

这是一个常见问题。

您正在修改源代码中的文字常量数据。 LIST调用中的con单元格都是文字常量。您已经引用了它们。

使用lamdba x,y: Value.Success(y+1, x) if x[y] == "<" else Value.failure(y, x) 创建一个新列表。

copy-tree

或者调用(let ((counter (copy-tree '((a . 0) (c . 0) (g . 0) (t . 0))))) ...) 而不是引用cons单元格。