2011-10-18 19 views
2

私は質問があるCommonLispのnoobです。私は以下の2つの機能を持っています。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))))) 

そして主な機能:私は(test-return-rhythms '(1/4 1/8))を実行すると

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

、それが評価されます。((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) 

、あなたのテストを実行するのであれば、2回目の反復は(-1/4 -1/8)、および(make-rests '(0) '(-1/4 -1/8))戻り(1/4 -1/8)が表示されます。 make-restsletを使用してもリストはコピーされません。リストを参照する新しいバインディングが作成されます。あなたのletcopy-listを使用するか、最初の場所で非破壊バージョンを記述します。

(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