以下是我會處理這個問題:
(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