如何在Common Lisp中创建连续数字列表?
换句话说,在Common Lisp中,什么是Python的range
函数的等价物?
在Python中,range(2, 10, 2)
返回[2, 4, 6, 8]
,第一个和最后一个参数是可选的。虽然Emacs Lisp有number-sequence
,但我找不到创建数字序列的惯用方法。
Range可以被模拟为using loop macro,但我想知道生成具有起点和终点以及步长的数字序列的公认方法。
发布于 2012-12-19 00:47:51
没有内置的方法来生成数字序列,规范的方法是执行以下操作之一:
使用使用loop
的实用程序函数loop
一个示例实现是(这只接受从“低”到“高”的计数):
(defun range (max &key (min 0) (step 1))
(loop for n from min below max by step
collect n))
这允许您指定(可选)最小值和(可选)步长值。
生成奇数:(range 10 :min 1 :step 2)
发布于 2012-12-27 19:35:40
alexandria实现了方案的iota:
(ql:quickload :alexandria)
(alexandria:iota 4 :start 2 :step 2)
;; (2 4 6 8)
发布于 2012-12-19 01:52:31
下面是我解决这个问题的方法:
(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
https://stackoverflow.com/questions/13937520
复制相似问题