在Emacs Lisp中逐步迭代

时间:2014-03-23 13:48:23

标签: emacs elisp slice

我在Elisp中有一个列表。如何从第1个开始返回包含每个第n个元素的列表?在Python中我有切片表示法:

>>> range(10)[::3]
[0, 3, 6, 9]

我在dash.el列表API中找不到任何有用的内容,所以我使用loop macro编写了我的解决方案:

(defun step (n xs)
  (loop for x in xs by (lambda (xs) (nthcdr n xs))
        collect x))

ELISP> (step 3 (number-sequence 0 10))
(0 3 6 9)

顺便说一句,(lambda (xs) (nthcdr n xs))可以使用dash.el的部分申请函数-partial重写:(-partial 'nthcdr n)

loop宏似乎有点矫枉过正。我如何在Emacs Lisp中逐步返回元素?

2 个答案:

答案 0 :(得分:3)

这是一个简短的插图,比较使用-partial和循环中的普通lambda:

(require 'cl-lib)

(prog1 nil
  (setq bigdata (number-sequence 1 10000)))

(defun every-nth-1 (n xs)
  (cl-loop for x in xs by (lambda (xs) (nthcdr n xs))
     collect x))

(defun every-nth-2 (n xs)
  (cl-loop for x in xs by (-partial 'nthcdr n)
     collect x))

(defmacro util-timeit (expr)
  (let ((t-beg (float-time))
        (res (dotimes (i 1000)
               (eval expr)))
        (t-end (float-time)))
    (/
     (- t-end t-beg)
     1000)))

(setq time1
      (util-timeit
       (length (every-nth-1 3 bigdata))))

(setq time2
      (util-timeit
       (every-nth-2 3 bigdata)))

(message "%s" (/ time2 time1))

调用eval-buffer会给我一个大约4的结果。这意味着 (lambda (xs) (nthcdr n xs))(-partial 'nthcdr n)快4倍, 至少没有字节编译。

通过字节编译,它在性能上给出了惊人的12.2-13.6倍的差异 赞成平原的lambda!

答案 1 :(得分:2)

dash软件包slice支持2.7版本的步骤。因此,Python的range(10)[1:7:2]等同于:

(-slice (number-sequence 0 9) 1 7 2) ; (1 3 5)