进程列表修改elisp中的元素

时间:2016-03-24 14:15:40

标签: list emacs foreach elisp

我是elisp的新手,仍在学习如何用C或Perl编写的内容转换为相应的elisp代码。在特定情况下,我需要处理一个列表元素 - 修改这些。我考虑过dolist,但与Perl的foreach不同,我无法修改原始列表值。我提出了以下代码,但它看起来过于复杂(至少对我来说看起来不太可读):

(setq x '("a" "b" "c"))
(let ((p x))
  (while (car p)
    (setcar p (concat ">" (car p)))
    (setq p (cdr p))))

有没有更好的方法来实现同样的目标?

3 个答案:

答案 0 :(得分:1)

我建议您尝试考虑如何在没有修改列表的情况下执行您想要的操作。即相反,返回另一个列表。例如:

(let ((newlist
       (mapcar (lambda (p) (concat ">" p))
               x)))
  ...use newlist...)

答案 1 :(得分:1)

{em> not dolist阻止您修改列表元素。您在dolist中声明的局部变量将绑定到列表的后续元素 - 实际元素,而不是它们的副本。您可以做任何想要修改这些单独元素的事情。

您可能感到困惑的是原始列表 - 或任何列表 - 可能包含这些元素。

例如:

(defun foo (xs)
  (dolist (x xs) (setcar x 3)))

(setq bar '((2 2) (4 4 4) (6 6 6)))

(foo bar)

C-h v bar向您显示列表bar确实已通过dolist代码更改了每个元素:

bar's value is 
((3 2)
 (3 4 4)
 (3 6 6))

bar仍然指向相同的cons单元格,但列表中的每个元素都将其car设置为3。

更新以回复@duthen:

这不是“bar [仍然指向]同一个cons小区的每个元素”。

这是关于列表修改。要么替换(或以其他方式更改)特定列表中的实际元素,要么不要。如果你这样做,你当然可以使用dolist来做到这一点。这些要素不一定是一致的。

但是,如果您只想替换特定列表元素,则意味着您不想修改该列表的顶级列表结构。否则,您将构建一个新列表,而不是仅修改现有列表的元素。

dolist本身不会修改其list参数的顶级列表结构。但它根本不会阻止您更改该列表中的元素。这包括更改他们的列表结构,如果它们本身就是列表(conses),就像我上面的示例一样。 dolist本身不是树操作。

这是另一个例子,其中列表元素是字符串。同样,元素本身被修改 - 替换,但包含它们的列表是相同的(此列表只有顶级列表结构)。

(defun foo (xs)
  (dolist (x xs) (setf (aref x 0) ?$)))

(setq bar '("abc" "def" "ghij"))

(foo bar)

bar的列表值确实已更改。它的元素不一样 - 它们已被不同的值所取代。列表的缺点单元格是相同的缺点单元格,但它们的汽车没有相同的值。

dolist只允许您访问列表中的各个元素。它不允许您访问构成列表本身的顶级conses。您无法使用dolist将元素"abc"替换为元素42,因为您无法修改前一个对象以提供后者。如果你想进行这样的替换,那么你需要访问列表的conses ,而不仅仅是列表中的元素。元素只是构成列表的顶级conses的汽车。

问题提出的问题是:“处理列表元素 - 修改这些”。正如这些例子所示,这完全可以使用dolist。无法修改"abc"以向您42。如果你想要那种元素替换,那么你需要修改列表conses。

如果问题的意思不同,则不清楚。

答案 2 :(得分:1)

嗯......因为我是法国人,我不确定我能说清楚我的意思......

“修改原始列表值”是不明确的,例如“修改列表元素”。

Drew,在您的示例中,您演示了使用dolist,您可以枚举列表,并且对于列表中的每个项目,您可以应用将更改的函数(如setcar)内容里面这个项目。

确定。

但是,使用dolist,您无法用其他项替换列表中的每个项目,例如将p替换为(concat ">" p)

在您的示例中,列表(2 2)的{​​{1}}列表为eq

所以你可以说(3 2)仍然指向同一个cons单元格,并且bar的每个元素仍然指向同一个cons单元格。

我们可以说你改变/修改了第一个元素(用法语,“vousavezchangé le premierééément”),但你不能说你替换了第一个元素(“vousavezchangé” de premierééément“)。

Aamof,有趣的是,在法语中,只有一个不同的字母!

无论如何,您无法使用bar执行此操作,但可以使用dolist执行此操作:

do