有没有办法调整 Common Lisp dotimes 宏,使其不是从零开始而是从不同的数字开始,比如 1?

Is there a way to tweak Common Lisp dotimes macro so that it does not start from zero but from a different number, such as 1?

我正在使用 Emacs、Slime 和 SBCL。

默认使用dotimes是:

CL-USER> (defun my-dotimes (n)
           (dotimes (i n)
             (format t "~s ~%" i)))

生成:

CL-USER> (my-dotimes 10)
0 
1 
2 
3 
4 
5 
6 
7 
8 
9 
NIL

我希望这个功能可以从一开始计数。我可以更改它:

CL-USER> (defun my-new-dotimes (n)
           (dotimes (i (- n 1))
             (format t "~s ~%" (+ i 1))))
MY-NEW-DOTIMES
CL-USER> (my-new-dotimes 10)
1 
2 
3 
4 
5 
6 
7 
8 
9 
NIL

但是,感觉这不是一个优雅的解决方案。

官方documentation提到了declare的可能性。但是不知道怎么用。

有更好的方法吗?

不,dotimes 无法做到这一点。如果您想要一个从 1 开始计数的宏,请使用 loopdo 或编写一个。

使用do:

(do ((i 1 (1+ i))
    ((> i 10))
  ...)
CL-USER 15 > (defmacro dotimes-start ((var n start
                                       &optional (result nil))
                                      &body body)
               `(loop for ,var from ,start
                      repeat ,n
                      do (progn ,@body)
                      finally (return ,result)))
DOTIMES-START

CL-USER 16 > (dotimes-start (i 10 2) (print i))

2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
NIL

CL-USER 17 > (let ((s 0))
               (dotimes-start (i 10 3 s)
                 (incf s (sin i))))
-1.8761432