我正在查看dotimes
上的LispWorks Hyperspec,但我不明白第三个变量[result-form]
正在做什么。示例如下:
(dotimes (temp-one 10 temp-one)) => 10
(setq temp-two 0) => 0
(dotimes (temp-one 10 t) (incf temp-two)) => T
temp-two => 10
Hyperspec说
...然后评估结果形式。当时结果形式是 处理后,var与执行正文的次数绑定。
不确定这是什么意思。为什么这两个dotimes
示例中需要第三个变量?我似乎完全可以在第二个例子中完全放弃它,它可以工作。我的下一个例子(不知道我在哪里找到它),
(defun thing (n)
(let ((s 0))
(dotimes (i n s)
(incf s i))))
也困惑我。 s
服务的用途是什么?
答案 0 :(得分:4)
由于 dotimes 是一个宏,因此查看它的宏扩展可以让事情更清晰:
拿第一个例子展开它:
(pprint (MACROEXPAND-1 '(dotimes (temp-one 10 temp-one))))
我得到以下输出:(你的可能因CL实现而异)
(BLOCK NIL
(LET ((#:G8255 10) (TEMP-ONE 0))
(DECLARE (CCL::UNSETTABLE TEMP-ONE))
(IF (CCL::INT>0-P #:G8255)
(TAGBODY
#:G8254 (LOCALLY (DECLARE (CCL::SETTABLE TEMP-ONE))
(SETQ TEMP-ONE (1+ TEMP-ONE)))
(UNLESS (EQL TEMP-ONE #:G8255) (GO #:G8254))))
TEMP-ONE))
有很多事情要发生,但要注意的关键是temp-one绑定到值0,并作为表达式的值返回(以标准的lisp评估顺序)。
拿最后一个例子:
(pprint (macroexpand-1 '(dotimes (i n s) (incf s i))))
输出:
(BLOCK NIL
(LET ((#:G8253 N) (I 0))
(DECLARE (CCL::UNSETTABLE I))
(IF (CCL::INT>0-P #:G8253)
(TAGBODY
#:G8252 (INCF S I)
(LOCALLY (DECLARE (CCL::SETTABLE I))
(SETQ I (1+ I)))
(UNLESS (EQL I #:G8253) (GO #:G8252))))
S))
正如你所看到的,这里的S与前面例子中的temp-one相同。
在不传递最后一个变量的情况下尝试一个:
(pprint (macroexpand-1 '(dotimes (i n) (do-something i))))
你得到:
(BLOCK NIL
(LET ((#:G8257 N) (I 0))
(DECLARE (CCL::UNSETTABLE I))
(IF (CCL::INT>0-P #:G8257)
(TAGBODY
#:G8256 (DO-SOMETHING I)
(LOCALLY (DECLARE (CCL::SETTABLE I))
(SETQ I (1+ I)))
(UNLESS (EQL I #:G8257) (GO #:G8256))))
NIL))
注意NIL是如何返回值。