2011-10-18 35 views
2

我是CommonLisp noob,提问。下面我有这两个功能。Dolist评估错误

一个辅助函数:

(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

您对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)。您在make-rests中使用let不会复制列表,它只是创建一个引用它的新绑定。使用copy-listlet,或写在首位非破坏性版本:

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

啊,请注意,此功能将更好地命名为'拨动rests'。 – danlei

+0

非常感谢! – user998509