由於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的處理方式與溫度,一個在之前的例子一樣。
嘗試以下一項,而沒有經過最後一個變量:
(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是怎樣的返回值。
結果窗體只是一個表單,它在循環完成後被評估爲產生返回值(或多個)。它是可選的(如果你不出來,返回值將是'NIL')。在你的最後一個例子中,變量'S'用於累計在循環結尾返回的'N'下的所有整數的和。 – jkiiski