我使用local-time编写了以下循环:
(defun count-dates(停止日期k) (循环步骤=(当地时间:今天) 然后(当地时间:时间戳 - 第1步:每天) 而(当地时间:……
你也可以使用 系列 包:
(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 :
#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 函数,它可以直接将代码表示为循环。例如:
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
你可以通过带来一个级别的缩进去除 reverse 在里面打电话 还要注意名称 count-dates 并不是那么好,因为一个人不计算日期,而是将一个函数从今天的downto映射到一天 stop-date 。
reverse
count-dates
stop-date
(defun count-dates2 (stop-date k) (labels ((f (acc step) (if (local-time:timestamp>= step stop-date) (f (cons (funcall k step) acc) (local-time:timestamp- step 1 :day)) (reverse acc)))) (f '() (local-time:today)))))
另一个迭代构造是旧的 DO :
DO
(defun count-dates (stop-date k &aux result) (do ((step (local-time:today) (local-time:timestamp- step 1 :day))) ((not (local-time:timestamp>= step stop-date)) (reverse result)) (push (funcall k step) result)))
但那并不比 LOOP 。
LOOP
迭代构造,它不是标准的,但功能强大 LOOP 而且在美学上略胜一筹 重复 。