Elisp 中各种形式的循环和迭代

Various forms of looping and iteration in Elisp

我试图理解 Emacs Lisp 中的所有循环结构。 在一个示例中,我尝试遍历符号列表并将它们打印到 *message* 缓冲区,如下所示:

(let* ((plist package-activated-list) ;; list of loaded packages
       (sorted-plist (sort plist 'string<)))
  (--map (message (format "%s" it)) sorted-plist))

--map 是包 dash.el.

中的一个函数

如何在纯 Elisp 中执行此操作?

现在如何在不使用其他包的情况下在 Elisp 中迭代列表。

我看过一些使用 whiledolist 宏的例子,例如这里:

https://www.gnu.org/software/emacs/manual/html_node/elisp/Iteration.html

但这些都是破坏性的、非功能性的循环表达方式。

来自 Scheme(大约二十年前使用它和 SICP!),我倾向于更喜欢功能性的、非破坏性的(这是否总是导致递归?)表达想法的方式。

那么在 Emacs Lisp 中遍历项目列表的惯用方法是什么?

另外:有没有办法在 Emacs Lisp 中以函数式方式表达循环?

到目前为止我发现了什么

  1. 循环宏(来自 Common Lisp?)前缀为“cl-*”

https://www.gnu.org/software/emacs/manual/html_node/cl/Loop-Facility.html

  1. 迭代子句

https://www.gnu.org/software/emacs/manual/html_node/cl/Iteration-Clauses.html#Iteration-Clauses

  1. Dash.el

https://github.com/magnars/dash.el

Magnar Sveen 的优秀软件包作为“Emacs 的现代列表 api。不需要 'cl'。”

还有什么?有推荐读物吗?

dolist 不是破坏性的,这可能是 Emacs Lisp 或 Common Lisp 中最惯用的方式,当您只想依次对每个成员做某事时循环遍历列表:

(setq *properties* '(prop1 prop2 prop3))

(dolist (p *properties*)
  (print p))

seq-doseq 函数的作用与 dolist 相同,但它接受序列参数(例如,列表、向量或字符串):

(seq-doseq (p *properties*)
  (print p))

如果需要更实用的样式,seq-do function applies a function to the elements of a sequence and returns the original sequence. This function is similar to the Scheme procedure for-each,它也用于它的副作用。

(seq-do #'(lambda (p) (print p)) *properties*)

有许多本机 ~map~ 函数可供您探索以遍历列表,其中包含一些小技巧或糖分。

在这种情况下,我选择 `mapconcat',它是从 C 代码加载的。

(mapconcat #'message sorted-plist "\n")

如果您正在寻找更传统的 Lisp map 函数,e-lisp 有它们:

https://www.gnu.org/software/emacs/manual/html_node/elisp/Mapping-Functions.html#Mapping-Functions

在您的代码片段中,mapc 可能是您想要的(丢弃值,只需应用函数;如果您需要值,mapcar 仍然存在):

(mapc #'(lambda (thing) (message (format "%s" thing))) sorted-plist)