2017-07-29 14 views
0

我正在查看dotimes上的LispWorks Hyperspec,但我不明白第三个变量[result-form]正在做什么。例子如下:解释Lisp的点子:什么是结果形式?

(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服务有什么用?

+1

结果窗体只是一个表单,它在循环完成后被评估为产生返回值(或多个)。它是可选的(如果你不出来,返回值将是'NIL')。在你的最后一个例子中,变量'S'用于累计在循环结尾返回的'N'下的所有整数的和。 – jkiiski

回答

3

由于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是怎样的返回值。