Common lisp &引用;“做”;未绑定宏变量定义

Common lisp &引用;“做”;未绑定宏变量定义,common-lisp,Common Lisp,我已经使用DO宏(使用Peter Seibel的书作为参考)编写了一个函数,但出于某种原因,当我编译我的函数时: (defun test () (do ((n 2 (1+ n)) (m 1 (1+ m)) (a (1+ n)) (b (1+ m)) (c (+ n m))) ((= n 10) (* a b c)) (print (* a b c)))) 我收到以下警告消息: WARNING: in TEST

我已经使用DO宏(使用Peter Seibel的书作为参考)编写了一个函数,但出于某种原因,当我编译我的函数时:

(defun test ()
  (do ((n 2 (1+ n))
       (m 1 (1+ m))
       (a (1+ n))
       (b (1+ m))
       (c (+ n m)))
      ((= n 10) (* a b c))
      (print (* a b c))))
我收到以下警告消息:

WARNING: in TEST in lines 1..10 : N is neither declared nor bound,
         it will be treated as if it were declared SPECIAL. 
WARNING: in TEST in lines 1..10 : M is neither declared nor bound,
         it will be treated as if it were declared SPECIAL. 
WARNING: in TEST in lines 1..10 : N is neither declared nor bound,
         it will be treated as if it were declared SPECIAL. 
WARNING: in TEST in lines 1..10 : M is neither declared nor bound,
         it will be treated as if it were declared SPECIAL.
当我尝试执行
test
时,它说
n
没有值

我的印象是,装订的顺序并不重要,但我还是尝试重新排列,结果还是一样的

我错过了什么?


在创建任何变量绑定之前,我正在使用CLISP 2.49对变量的所有初始化表单进行求值。这意味着绑定对同一
DO
中的init表单不可见

代码应该改为使用
DO*
,尽管输出不是很有趣,因为
A
B
C
从未更改

(defun test ()
  (do* ((n 2 (1+ n))
        (m 1 (1+ m))
        (a (1+ n))
        (b (1+ m))
        (c (+ n m)))
       ((= n 10) (* a b c))
    (print (* a b c))))

(test)
; 18 
; 18 
; 18 
; 18 
; 18 
; 18 
; 18 
;=> 18

DO*
在其他方面与
DO
相同,但它逐个计算并建立绑定,因此您可以在init表单中引用前面的变量。使用step表单更新变量时也会执行相同操作。

DO
在创建任何变量绑定之前,对变量的所有初始表单进行求值。这意味着绑定对同一
DO
中的init表单不可见

代码应该改为使用
DO*
,尽管输出不是很有趣,因为
A
B
C
从未更改

(defun test ()
  (do* ((n 2 (1+ n))
        (m 1 (1+ m))
        (a (1+ n))
        (b (1+ m))
        (c (+ n m)))
       ((= n 10) (* a b c))
    (print (* a b c))))

(test)
; 18 
; 18 
; 18 
; 18 
; 18 
; 18 
; 18 
;=> 18

DO*
在其他方面与
DO
相同,但它逐个计算并建立绑定,因此您可以在init表单中引用前面的变量。使用step表单更新变量时也会执行相同操作。

DO
创建的绑定对于
DO
中的init表单不可见。您可能希望
DO*
,但我不确定循环应该做什么。变量
A
B
C
没有阶跃形式,因此它们的值永远不会改变。也许你丢失了这些的init表单?@jkiiski谢谢你的评论。我不知道它们在init表单中不可用。我想,既然我可以在步骤表单中使用它们,那么它在任何地方都可以使用:/As为了循环的目的,为了这个问题,我删除了主体和返回值。这在上下文中是有意义的!您建议我如何绕过init表单限制?使用
do*
而不是
do
应该可以,除非您需要在任何赋值之前对步骤表单进行求值(情况似乎并非如此,除非代码中没有显示更多变量)。@jkiiski非常感谢您的回答。你应该写一个评论摘要作为答案,这样我可以给你一些信任。由
DO
创建的绑定对于
DO
中的init表单是不可见的。您可能希望
DO*
,但我不确定循环应该做什么。变量
A
B
C
没有阶跃形式,因此它们的值永远不会改变。也许你丢失了这些的init表单?@jkiiski谢谢你的评论。我不知道它们在init表单中不可用。我想,既然我可以在步骤表单中使用它们,那么它在任何地方都可以使用:/As为了循环的目的,为了这个问题,我删除了主体和返回值。这在上下文中是有意义的!您建议我如何绕过init表单限制?使用
do*
而不是
do
应该可以,除非您需要在任何赋值之前对步骤表单进行求值(情况似乎并非如此,除非代码中没有显示更多变量)。@jkiiski非常感谢您的回答。你应该写一个评论摘要作为回答,这样我可以给你一些信用。