以下是我会处理这个问题:
(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
我使用'delay'和'force'实现了类似的东西。这模仿Python的'范围'。 – sean
@sean'xrange'肯定? – Vatine
@Vatine,True,但也取决于python版本当然。 – sean