您也可以使用SERIES 包:
(defpackage :so (:use :cl :series :local-time))
(in-package :so)
(let ((stop-date (timestamp- (today) 10 :day)))
(scan-fn ;; type of elements (could be T here)
'timestamp
;; init function
(lambda () (today))
;; step function
(lambda (ts) (timestamp- ts 1 :day))
;; termination test
(lambda (ts) (not (timestamp>= ts stop-date)))))
上面返回一个系列对象的实例,它是一个惰性(按需)值流,被高效编译。在 REPL 中,这显示为 #Z(...)(其中点是元素)。如果你想把它转换成一个列表,你可以打电话给collect:
(collect *) ;; assuming * is the last returned value
如果你想要一个向量:
(collect 'vector **)
这给出了:
#(@2019-02-19T01:00:00.000000+01:00 @2019-02-18T01:00:00.000000+01:00
@2019-02-17T01:00:00.000000+01:00 @2019-02-16T01:00:00.000000+01:00
@2019-02-15T01:00:00.000000+01:00 @2019-02-14T01:00:00.000000+01:00
@2019-02-13T01:00:00.000000+01:00 @2019-02-12T01:00:00.000000+01:00
@2019-02-11T01:00:00.000000+01:00 @2019-02-10T01:00:00.000000+01:00
@2019-02-09T01:00:00.000000+01:00)
还要注意,在collect 词法包含scan-fn 函数的情况下,它可以直接将代码表示为循环。例如:
(let ((stop-date (timestamp- (today) 10 :day)))
(collect
(scan-fn ;; type of elements (could be T here)
'timestamp
;; init function
(lambda () (today))
;; step function
(lambda (ts) (timestamp- ts 1 :day))
;; termination test
(lambda (ts) (not (timestamp>= ts stop-date))))))
collect 表单被宏扩展为:
(LET* (#:STATE-1062 #:ITEMS-1063 (#:LASTCONS-1060 (LIST NIL)) #:LST-1061)
(DECLARE (TYPE CONS #:LASTCONS-1060)
(TYPE LIST #:LST-1061))
(LOCALLY
(DECLARE (TYPE TIMESTAMP #:STATE-1062)
(TYPE TIMESTAMP #:ITEMS-1063))
(SETQ #:STATE-1062 ((LAMBDA () (TODAY))))
(SETQ #:LST-1061 #:LASTCONS-1060)
(TAGBODY
#:LL-1064
(IF ((LAMBDA (TS) (NOT (TIMESTAMP>= TS STOP-DATE))) #:STATE-1062)
(GO SERIES::END))
(SETQ #:ITEMS-1063 #:STATE-1062)
(SETQ #:STATE-1062 ((LAMBDA (TS) (TIMESTAMP- TS 1 :DAY)) #:STATE-1062))
(SETQ #:LASTCONS-1060
(SETF (CDR #:LASTCONS-1060) (CONS #:ITEMS-1063 NIL)))
(GO #:LL-1064)
SERIES::END)
(CDR #:LST-1061)))
正如 Evhince 所提到的,Common Lisp 食谱有一个关于系列的部分,请参阅 https://lispcookbook.github.io/cl-cookbook/iteration.html