You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Common Lisp中DO循环输出与预期不符的原因及执行流程解析

Common Lisp do 循环执行流程与输出解析

原代码

(setq x 10)
(setq y 30)

(do ((x       0 (+ 3 x)) 
     (y      20 (- y 2))
     (z (- y x) (- z x)))
    ((> x y) (- x y))           ; exit condition
  (format t "~% z = ~d" z))     ; print local variable Z

(format t "x = ~d y = ~d" x y)  ; print global variables X and Y

预期输出

z = 20
z = 17
z = 11
z = 2
z = -10
x = 15 y = 10

疑惑解答

1. 迭代过程中变量x、y、z是如何更新的?

Common Lisp的do循环采用并行绑定规则处理迭代变量:

  • 初始化阶段:所有变量的初始值同时计算,若引用外部变量(比如z的初始值(- y x)),会使用全局变量的值(此时局部变量还未绑定)。
  • 更新阶段:每次循环体执行后,所有变量的新值基于上一轮迭代结束时的旧值并行计算——也就是说,某变量的新值不会影响同一轮其他变量的更新计算。
  • 注意:do内的x、y是局部变量,和全局的x、y完全独立,不会互相干扰。

2. 为何我的预期输出不正确?

你的预期错误源于两个核心误解:

  • 误解了do的变量更新逻辑:你以为变量是顺序更新的(比如先更新x,再用新x计算z的新值),但实际是并行更新,所有更新表达式都使用上一轮的旧值。
  • 混淆了局部变量和全局变量:你以为do内的x、y会修改全局变量,但do的迭代变量是局部绑定的,循环结束后全局变量的值不会改变。

3. 正确输出是什么,原因是什么?

正确输出:

z = 20
z = 20
z = 17
z = 11
z = 2
x = 10 y = 30

执行流程解析:

  1. 全局变量初始化:x=10,y=30。
  2. do循环局部变量初始化:
    • 局部x=0,局部y=20,局部z=全局y-全局x=30-10=20。
  3. 第一次循环:
    • 退出条件(>0 20)为假,执行循环体,打印z = 20。
    • 并行计算更新值:新x=0+3=3,新y=20-2=18,新z=20-0=20(用上一轮旧值计算)。
  4. 第二次循环:
    • 退出条件(>3 18)为假,执行循环体,打印z = 20。
    • 并行计算更新值:新x=3+3=6,新y=18-2=16,新z=20-3=17。
  5. 第三次循环:
    • 退出条件(>6 16)为假,执行循环体,打印z = 17。
    • 并行计算更新值:新x=6+3=9,新y=16-2=14,新z=17-6=11。
  6. 第四次循环:
    • 退出条件(>9 14)为假,执行循环体,打印z = 11。
    • 并行计算更新值:新x=9+3=12,新y=14-2=12,新z=11-9=2。
  7. 第五次循环:
    • 退出条件(>12 12)为假,执行循环体,打印z = 2。
    • 并行计算更新值:新x=12+3=15,新y=12-2=10,新z=2-12=-10。
  8. 退出判断:
    • 退出条件(>15 10)为真,循环结束,不执行循环体。
  9. 最后打印全局变量:x=10,y=30(局部变量不影响全局)。

内容的提问来源于stack exchange,提问作者Hasan Saafen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 15:56:10