这是我解决问题的方法:
(defun generate (from to &optional (by 1))
#'(lambda (f)
(when (< from to)
(prog1 (or (funcall f from) t)
(incf from by)))))
(defmacro with-generator ((var from to &optional (by 1)) &body body)
(let ((generator (gensym)))
`(loop with ,generator = (generate ,from ,to ,by)
while
(funcall ,generator
#'(lambda (,var) ,@body)))))
(with-generator (i 1 10)
(format t "~&i = ~s" i))
但这只是大体思路,还有很大的改进空间。
好的,因为这里似乎有讨论。我假设真正需要的是类似于 Python 的 range 生成器函数。从某种意义上说,它会生成一个数字列表,但它是通过每次迭代产生一个数字来实现的(这样它一次不会创建一个以上的项目)。生成器是一个比较少见的概念(很少有语言实现它),所以我假设提到 Python 表明需要这个确切的特性。
在对我上面的示例进行一些批评之后,这里有一个不同的示例来说明为什么可以使用生成器而不是简单循环的原因。
(defun generate (from to &optional (by 1))
#'(lambda ()
(when (< from to)
(prog1 from
(incf from by)))))
(defmacro with-generator
((var generator &optional (exit-condition t)) &body body)
(let ((g (gensym)))
`(do ((,g ,generator))
(nil)
(let ((,var (funcall ,g)))
(when (or (null ,var) ,exit-condition)
(return ,g))
,@body))))
(let ((gen
(with-generator (i (generate 1 10) (> i 4))
(format t "~&i = ~s" i))))
(format t "~&in the middle")
(with-generator (j gen (> j 7))
(format t "~&j = ~s" j)))
;; i = 1
;; i = 2
;; i = 3
;; i = 4
;; in the middle
;; j = 6
;; j = 7
同样,这只是此功能用途的说明。使用它来生成整数可能很浪费,即使您需要分两步执行此操作,但生成器最好使用解析器,当您想要生成基于解析器先前状态构建的更复杂的对象时,例如,还有一堆其他的东西。好吧,您可以在这里阅读有关它的论点:http://en.wikipedia.org/wiki/Generator_%28computer_programming%29