Dolist评估错误

时间:2011-10-18 03:42:01

标签: common-lisp

我是一个带问题的CommonLisp菜鸟。我在下面有这两个功能。

辅助功能:

(defun make-rests (positions rhythm)
  "now make those positions negative numbers for rests"
  (let ((resultant-rhythm rhythm))
    (dolist (i positions resultant-rhythm)
      (setf (nth i resultant-rhythm) (* (nth i resultant-rhythm) -1)))))

主要功能:

(defun test-return-rhythms (rhythms)
  (let ((positions '((0 1) (0)))
        (result nil))
    (dolist (x positions (reverse result))
      (push (make-rests x rhythms) result))))

当我运行(test-return-rhythms '(1/4 1/8))时,它会评估为:((1/4 -1/8) (1/4 -1/8))

但是,我希望:(test-return-rhythms '(1/4 1/8))评估为:((-1/4 -1/8) (-1/4 1/8))

我做错了什么?

1 个答案:

答案 0 :(得分:1)

make-rests的实施具有破坏性。

CL-USER> (defparameter *rhythm* '(1/4 1/4 1/4 1/4))
*RHYTHM*
CL-USER> (make-rests '(0 2) *rhythm*)
(-1/4 1/4 -1/4 1/4)
CL-USER> *rhythm*
(-1/4 1/4 -1/4 1/4)

因此,如果您运行测试,第二次迭代将看到(-1/4 -1/8)(make-rests '(0) '(-1/4 -1/8))将返回(1/4 -1/8)。您在let中使用make-rests不会复制列表,只会创建一个引用它的新绑定。在copy-list中使用let,或者首先编写非破坏性版本:

(defun make-rests (positions rhythm)
  (loop for note in rhythm
        for i from 0
        collect (if (member i positions) (* note -1) note)))