首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Python的range()在Common Lisp中的模拟

Python的range()在Common Lisp中的模拟
EN

Stack Overflow用户
提问于 2012-12-19 00:39:42
回答 9查看 11.7K关注 0票数 35

如何在Common Lisp中创建连续数字列表?

换句话说,在Common Lisp中,什么是Python的range函数的等价物?

在Python中,range(2, 10, 2)返回[2, 4, 6, 8],第一个和最后一个参数是可选的。虽然Emacs Lisp有number-sequence,但我找不到创建数字序列的惯用方法。

Range可以被模拟为using loop macro,但我想知道生成具有起点和终点以及步长的数字序列的公认方法。

相关:Analog of Python's range in Scheme

EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2012-12-19 00:47:51

没有内置的方法来生成数字序列,规范的方法是执行以下操作之一:

使用使用loop的实用程序函数loop

  • Write

一个示例实现是(这只接受从“低”到“高”的计数):

(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)

票数 40
EN

Stack Overflow用户

发布于 2012-12-27 19:35:40

alexandria实现了方案的iota:

(ql:quickload :alexandria)
(alexandria:iota 4 :start 2 :step 2)
;; (2 4 6 8)
票数 19
EN

Stack Overflow用户

发布于 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

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13937520

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档