我明白了
(dotimes (temp-one 10 temp-one))
来自dotimes
上的Hyperspec示例。运行此命令将得出答案10。因此,位于第三个参数位置的temp-one
充当返回的“结果”,但是当dotimes
从0开始并仅变为9时,它如何达到10。 ?
>(dotimes (temp-one 10 temp-one) (format t "~3d " temp-one))
0 1 2 3 4 5 6 7 8 9
10
我在这里缺少第三个参数吗?
答案 0 :(得分:5)
如果您查看dotimes Hyperspec entry,则说明它是一个宏,这意味着您可以通过调用 macroexpand 来看到“内幕”:
(macroexpand '(dotimes (i 10 i)))
SBCL:
(BLOCK NIL
(LET ((I 0))
(DECLARE (TYPE UNSIGNED-BYTE I))
(TAGBODY
(GO #:G386)
#:G385
(TAGBODY)
(PSETQ I (1+ I))
#:G386
(UNLESS (>= I 10) (GO #:G385))
(RETURN-FROM NIL (PROGN I)))))
Allegro CL:
(do ((i 0 (1+ i)))
((>= i 10) i))
在两种情况下,迭代变量 i 均增加1,然后完成最终测试(>= i 10)
。正如jkiiski写道:
在变量增加并测试之后,对“在处理结果形式时, var 绑定到执行主体的次数。”
以及(return-from ..)
形式(SBCL)和i
形式(Allegro CL)进行评估。
答案 1 :(得分:4)
Hyperspec说:
在处理result-form时,var绑定到 尸体被处死的次数。
因此,在第三种形式(即结果形式)中,变量首先绑定到主体被执行的次数,然后对第三种形式进行求值。
这就是为什么变量值是10
而不是当前值9
的原因。
这也是可见的
(macroexpand-1 '(dotimes (temp-one 3 temp-one) (format t "~3d~%" temp-one)))
;; resulting in CLISP in:
;; (DO ((TEMP-ONE 0 (1+ TEMP-ONE))) ((>= TEMP-ONE 10) TEMP-ONE)
;; (FORMAT T "~3d~%" TEMP-ONE)) ;
;; T
最后,(1+ TEMP-ONE)
由DO
循环返回,DOTIMES
扩展到--如@zut所指出。