2017-09-14 80 views
0

我已经写了使用DO宏(用彼得·塞贝尔的书作为参考)功能,但由于某些原因,当我编译我的功能:“DO”宏变量定义不被束缚

(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

+0

由'DO'创建的绑定对那个'DO'中的init表单不可见。你可能需要'DO *',但我不确定循环应该做什么。变量'A','B'和'C'没有步骤形式,所以它们的值不会改变。也许你错过了那些初始形式? – jkiiski

+0

@jkiiski感谢您的评论。我不知道它们不是以初始形式提供的。我想,因为我可以在步骤形式中使用它们,所以无处不在:/ 至于循环的目的,为了解决问题,我删除了主体并返回了值。它在上下文中是有意义的!你会建议我如何解决初始表单限制? – Gab

+0

使用'DO *'而不是'DO'应该可以工作,除非您需要在任何赋值之前对所有步骤进行评估(似乎并非如此,除非您有更多变量未在代码中显示) 。 – jkiiski

回答

3

DO评估所有的init-形式的变量创建任何变量绑定之前。这意味着绑定对同一个DO中的初始表单不可见。

的代码应该工作使用DO*代替,虽然产量不是很有趣,因为ABC永远不会改变。

(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-形式。使用步骤更新变量时也完成了相同的操作。