在 elisp 中处理列表修改元素
Process list modifying elements in 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))))
有没有更好的方法来达到同样的效果?
我建议您尝试考虑如何在不修改列表的情况下做您想做的事。 IE。相反,返回另一个列表。例如:
(let ((newlist
(mapcar (lambda (p) (concat ">" p))
x)))
...use newlist...)
不是 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 单元格,但列表中的每个元素都将其汽车设置为 3。
更新回复@duthen:
这与 "each element of bar
[still pointing] to the same cons cell" 无关。
关于列表修改。您要么想要替换(或以其他方式更改)特定列表中的实际元素,要么不想。如果这样做,您当然可以使用 dolist
来做到这一点。元素不必是conses。
但是如果你只想替换特定列表的元素,这意味着你不想修改顶部-该列表的级别列表结构。否则,您将构建一个新列表,而不是仅修改现有列表的元素。
dolist
本身不会修改其列表参数的顶级列表结构。但它根本不会阻止您更改该列表中的 elements。这包括更改 他们的 列表结构,如果它们本身就是列表(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
,因为您无法修改前者对象以提供后者。如果您想进行这样的替换,那么您需要 访问列表的内容 而不仅仅是列表中的 元素 。元素只是构成列表的顶级cones的汽车。
题目提出的问题是这样的:"process a list element-wise modifying these"。如这些示例所示,使用 dolist
完全有可能。没办法修改"abc"
给你42
。如果你想要那种元素替换,那么你需要修改列表conses。
如果问题的含义不同,则不清楚。
嗯...因为我是法国人,所以我不确定我能否清楚地解释我的意思...
"modify the original list values" 有歧义,例如 "modifying the list elements".
Drew,在您的示例中,您演示了使用 dolist
,您可以枚举列表,并且对于列表中的每个项目,您可以应用一个函数(如 setcar
),它将更改此项目 中的某些内容。
好的。
但是,对于 dolist
,您不能将列表中的每一项替换为另一项,例如将 p
替换为 (concat ">" p)
。
在您的示例中,列表 (2 2)
是列表 (3 2)
的 eq
。
所以你可以说 bar
仍然指向同一个 cons 单元,并且 bar
的每个元素也仍然指向同一个 cons 单元。
我们可以说您 changed/modified 第一个元素(在法语中,"vous avez changé le premier élément"),但您不能说您替换了第一个元素 ("vous avez changé de premier élément")。
Aamof,有趣的是,在法语中,只有一个不同的字母!
无论如何,你不能用dolist
,但你可以用do
:
(do ((p x (cdr p)))
((null p) x)
(setcar p (concat ">" (car p))))
我是 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))))
有没有更好的方法来达到同样的效果?
我建议您尝试考虑如何在不修改列表的情况下做您想做的事。 IE。相反,返回另一个列表。例如:
(let ((newlist
(mapcar (lambda (p) (concat ">" p))
x)))
...use newlist...)
不是 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 单元格,但列表中的每个元素都将其汽车设置为 3。
更新回复@duthen:
这与 "each element of bar
[still pointing] to the same cons cell" 无关。
关于列表修改。您要么想要替换(或以其他方式更改)特定列表中的实际元素,要么不想。如果这样做,您当然可以使用 dolist
来做到这一点。元素不必是conses。
但是如果你只想替换特定列表的元素,这意味着你不想修改顶部-该列表的级别列表结构。否则,您将构建一个新列表,而不是仅修改现有列表的元素。
dolist
本身不会修改其列表参数的顶级列表结构。但它根本不会阻止您更改该列表中的 elements。这包括更改 他们的 列表结构,如果它们本身就是列表(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
,因为您无法修改前者对象以提供后者。如果您想进行这样的替换,那么您需要 访问列表的内容 而不仅仅是列表中的 元素 。元素只是构成列表的顶级cones的汽车。
题目提出的问题是这样的:"process a list element-wise modifying these"。如这些示例所示,使用 dolist
完全有可能。没办法修改"abc"
给你42
。如果你想要那种元素替换,那么你需要修改列表conses。
如果问题的含义不同,则不清楚。
嗯...因为我是法国人,所以我不确定我能否清楚地解释我的意思...
"modify the original list values" 有歧义,例如 "modifying the list elements".
Drew,在您的示例中,您演示了使用 dolist
,您可以枚举列表,并且对于列表中的每个项目,您可以应用一个函数(如 setcar
),它将更改此项目 中的某些内容。
好的。
但是,对于 dolist
,您不能将列表中的每一项替换为另一项,例如将 p
替换为 (concat ">" p)
。
在您的示例中,列表 (2 2)
是列表 (3 2)
的 eq
。
所以你可以说 bar
仍然指向同一个 cons 单元,并且 bar
的每个元素也仍然指向同一个 cons 单元。
我们可以说您 changed/modified 第一个元素(在法语中,"vous avez changé le premier élément"),但您不能说您替换了第一个元素 ("vous avez changé de premier élément")。
Aamof,有趣的是,在法语中,只有一个不同的字母!
无论如何,你不能用dolist
,但你可以用do
:
(do ((p x (cdr p)))
((null p) x)
(setcar p (concat ">" (car p))))