emacs的列表的一些操作函数


列表的常用函数

介绍 delete,remove,add-to-list,cons,nreverse函数。

0、简单定义一个列表:
(setq list1 '(alpha beta gamma))

列表的保存图示:

+-------+---+ +------+---+ +-------+-----+
list1--->| alpha | *----->| beta | *--->| gamma | nil |
+-------+---+ +------+---+ +-------+-----+
可以查阅ListStructure,如果你感到不明白上面的框图。

1、delete,在序列 SEQ 中找到和 ELT 匹配的元素并删除它,并返回指向列表的指针
(delete ELT SEQ)

ELISP> (setq list1 '(alpha beta gamma))
(alpha beta gamma)

ELISP> (setq list2 (delete 'beta list1))
(alpha gamma)

ELISP> (setq list3 (delete 'alpha list1))
(gamma)

list1、list2 和 list3 的值是什么?

下面先做一些解释:list1 是一个指针。它指向 alpha 单元格(这是一个包含 alpha 的 cons 单元格)和一个指向 beta 单元格的指针。beta单元格包含beta和一个指向gamma单元格的指针。gamma单元格包含gamma和nil,nil是列表的结束标记。

+-------+---+ +------+---+ +-------+-----+
list1--->| alpha | *----->| beta | *--->| gamma | nil |
+-------+---+ +------+---+ +-------+-----+
当执行第二句:(setq list2 (delete 'beta list1)),则会调用delete删除beta,并把结果存入list2中。由于删除了beta,则alpha的指针会指向gamma,然后delete函数返回指向alpha的指针,则list2 和 list1 现在有了同样的内容 alpha,gamma
+-------+---+ +------+---+ +-------+-----+
list1--->| alpha | *---+ | beta | *------+->| gamma | nil |
list2 +-------+---+ | +------+---+ | +-------+-----+
| |
+------------------+
当执行第三句,(setq list3 (delete 'alpha list1)),因为alpha是列表的首元素,因此不会有指针重定向。delete函数会把指向gamma的指针返回。因此list3的值是 gamma,但list1和list2并未改变。注意,这和预期不一样,delete删除列表首元素的时候,只能影响它自己的返回值,但列表并未改变。若要用delete来删除列表的首元素,就的把delete的返回值保存回列表,即 (setq list1 (delete 'alpha list))

+-------+---+ +-------+-----+
list1--->| alpha | *----->| gamma | nil |
list2 +-------+---+ +-------+-----+
^
|
list3---------------------+

gamma单元格被所有列表分享,beta不再被任何列表引用,它最终会被垃圾收集器收集。

2、remove 副本删除
(remove ELT SEQ)

要在不修改原始列表的情况下“删除”列表中的元素,请使用“remove”而不是“delete”。它返回一个删除了元素的原始列表的副本。请参阅“remove”的源代码,并查看它是使用“copy sequence”和“delete”实现的。
ELISP> (setq list1 '(alpha beta gamma))
(alpha beta gamma)

ELISP> (setq list2 (remove 'beta list1))
(alpha gamma)

ELISP> (setq list3 (remove 'alpha list1))
(beta gamma)

3、add-to-list 添加元素到列表

该函数的参数是:列表,添加的元素,add-to-list不会添加重复的元素,故常用于配置文件中。如果代码中向列表添加元素,用 push 函数。

ELISP> (setq list1 '(alpha beta gamma))
(alpha beta gamma)

ELISP> (add-to-list 'list1 'omega)
(omega alpha beta gamma)

ELISP> list1
(omega alpha beta gamma)

一个常用的配置,添加装载路径,load-path是一个路径的列表,向这个列表添加新路径,当然不希望有重复的,故用add-to-list
(add-to-list 'load-path "path/to/evil")

4、car,cdr,cons的来历

Lisp中car,cdr,cons都是基础函数,cons用于构造列表,car和cdr用于分割列表。
cons的名词来自单词“construct”的缩写。car是短语Contents of the Address part of the Register,cdr是短语Contents of the Decrement part of the Register,这些短语说明lisp是在多么原始的机器上被开发出来的。
cons 把一个元素添加到列表的开头,用这个函数可以添加大量的元素到列表中,你可以用nreverse来反转列表。

举例:

ELISP> (setq list1 '(alpha beta gamma))
(alpha beta gamma)

ELISP> (setq list2 (cdr list1))
(beta gamma)

ELISP> (setq list2 (cons 'ypsilon list2))
(ypsilon beta gamma)

ELISP> (eq list1 list2)
nil
ELISP> (eq (cdr list1) (cdr list2))
t

5、nreverse 反转列表
(nreverse SEQ),SEQ是序列的意思 sequence 序列。

(setq l1 '(one two three))
(one two three)
(nreverse l1)
(three two one)

6、push 向列表中添加元素
(push NEWELT PLACE)
(setq fea '())
nil
(push 'ooo fea)
(ooo)
(push 'bbb fea)
(bbb ooo)

posted @ 2022-04-28 10:05  立体风  阅读(247)  评论(0编辑  收藏  举报