多列表评估错误

发布于 2024-12-10 14:29:56 字数 778 浏览 1 评论 0原文

我是一名 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))

我做错了什么?

I'm a CommonLisp noob with a question. I have these two functions below.

A helper function:

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

And a main function:

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

When I run (test-return-rhythms '(1/4 1/8)), it evaluates to: ((1/4 -1/8) (1/4 -1/8))

However, I expected: (test-return-rhythms '(1/4 1/8)) to evaluate to: ((-1/4 -1/8) (-1/4 1/8)).

What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

早茶月光 2024-12-17 14:29:56

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

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

Your implementation of make-rests is destructive.

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)

So, if you run your test, the second iteration will see (-1/4 -1/8), and (make-rests '(0) '(-1/4 -1/8)) returns (1/4 -1/8). Your use of let in make-rests does not copy the list, it just creates a new binding that references it. Use copy-list in your let, or write a non-destructive version in the first place:

(defun make-rests (positions rhythm)
  (loop for note in rhythm
        for i from 0
        collect (if (member i positions) (* note -1) note)))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文