本节描述可以接受任意类型序列的函数。
如果 object 是列表、向量、字符串、布尔向量或字符表,该函数返回 t,否则返回 nil。另见下面的 seqp。
该函数返回 sequence 中的元素个数。如果参数不是序列或者是点列表(dotted list),函数会抛出 wrong-type-argument 错误;如果参数是循环列表(circular list),则抛出 circular-list 错误。对于字符表(char-table),返回的值总是比 Emacs 最大字符码大 1。
相关函数 safe-length,see Definition of safe-length。
(length '(1 2 3))
⇒ 3
(length ())
⇒ 0
(length "foobar")
⇒ 6
(length [1 2 3])
⇒ 3
(length (make-bool-vector 5 nil))
⇒ 5
另见 string-bytes,位于 Text Representations 中。
如果你需要计算字符串在显示时的宽度,应当使用 string-width(see Size of Displayed Text),而非 length。因为 length 只统计字符个数,不会考虑每个字符的实际显示宽度。
若 sequence 的长度小于 length,返回非 nil 值。如果 sequence 是一个很长的列表,使用该函数会比先计算列表长度再比较更高效。
若 sequence 的长度大于 length,返回非 nil 值。
若 sequence 的长度等于 length,返回非 nil 值。
该函数返回 sequence 中由 index 索引的元素。index 的合法取值是从 0 到序列长度减一的整数。若 sequence 是列表,超出范围的索引行为与 nth 一致,See Definition of nth。其他情况下,超出范围的索引会触发 args-out-of-range 错误。
(elt [1 2 3 4] 2)
⇒ 3
(elt '(1 2 3 4) 2)
⇒ 3
;; We use string to show clearly which character elt returns.
(string (elt "1234" 2))
⇒ "3"
(elt [1 2 3 4] 4)
error→ Args out of range: [1 2 3 4], 4
(elt [1 2 3 4] -1)
error→ Args out of range: [1 2 3 4], -1
该函数是对 aref(see 操作数组的函数)和 nth(see Definition of nth)的通用化。
该函数返回 seqr 的副本,seqr 应当是一个序列(sequence)或记录(record)。副本与原对象的类型完全相同,且包含与原对象顺序一致的相同元素。但如果 seqr 为空(例如长度为 0 的字符串或向量),该函数返回的值可能并非副本,而是与 seqr 类型相同、内容完全一致的空对象。
向副本中存入新元素不会影响原始的 seqr,反之亦然。但副本中的元素并非复制而来;它们与原对象的元素是完全相同的(通过 eq 判断为真)。因此,通过副本修改这些元素的内部内容时,对应的修改也会体现在原对象中。
若参数是带有文本属性(text properties)的字符串,则副本中的属性列表本身会被复制,不会与原字符串的属性列表共享。但属性的实际值仍为共享状态。See Text Properties。
该函数不适用于点列表(dotted lists)。尝试复制循环列表(circular list)可能会导致无限循环。
有关复制序列的其他方法,另请参见 构建 cons 单元与列表 中的 append 函数、创建字符串 中的 concat 函数,以及 向量相关函数 中的 vconcat 函数。
(setq bar (list 1 2))
⇒ (1 2)
(setq x (vector 'foo bar))
⇒ [foo (1 2)]
(setq y (copy-sequence x))
⇒ [foo (1 2)]
(eq x y)
⇒ nil
(equal x y)
⇒ t
(eq (elt x 1) (elt y 1))
⇒ t
;; Replacing an element of one sequence.
(aset x 0 'quux)
x ⇒ [quux (1 2)]
y ⇒ [foo (1 2)]
;; Modifying the inside of a shared element.
(setcar (aref x 1) 69)
x ⇒ [quux (69 2)]
y ⇒ [foo (69 2)]
该函数会创建一个新的序列,其元素为 sequence 的元素,但排列顺序完全反转。原始参数 sequence 不会 被修改。请注意,字符表(char-tables)无法被反转。
(setq x '(1 2 3 4))
⇒ (1 2 3 4)
(reverse x)
⇒ (4 3 2 1)
x
⇒ (1 2 3 4)
(setq x [1 2 3 4])
⇒ [1 2 3 4]
(reverse x)
⇒ [4 3 2 1]
x
⇒ [1 2 3 4]
(setq x "xyzzy")
⇒ "xyzzy"
(reverse x)
⇒ "yzzyx"
x
⇒ "xyzzy"
该函数会反转 sequence 中元素的排列顺序。与 reverse 函数不同的是,原始的 sequence 可能会被修改。
示例如下:
(setq x (list 'a 'b 'c))
⇒ (a b c)
x
⇒ (a b c)
(nreverse x)
⇒ (c b a)
;; The cons cell that was first is now last.
x
⇒ (a)
为避免产生混淆,我们通常会将 nreverse 函数的返回值重新存储到原本存放原始列表的同一个变量中:
(setq x (nreverse x))
以下是我们常用的示例 (a b c) 经 nreverse 函数处理后的结果,附带图形化展示:
Original list head: Reversed list: ------------- ------------- ------------ | car | cdr | | car | cdr | | car | cdr | | a | nil |<-- | b | o |<-- | c | o | | | | | | | | | | | | | | ------------- | --------- | - | -------- | - | | | | ------------- ------------
对于向量来说,操作更简单,因为你不需要使用 setq。
(setq x (copy-sequence [1 2 3 4]))
⇒ [1 2 3 4]
(nreverse x)
⇒ [4 3 2 1]
x
⇒ [4 3 2 1]
请注意,与 reverse 函数不同,本函数无法作用于字符串。尽管你可以通过 aset 函数修改字符串数据,但我们仍强烈建议你将字符串视为不可变对象 —— 即便它们本身具备可变特性。See 可变性。
该函数对 sequence 进行排序,该参数必须是列表或向量,并返回同类型的已排序序列。 该排序是稳定排序,即排序键相等的元素会保持它们原本的相对顺序。它接受下列可选关键字参数:
:key keyfunc使用 keyfunc 生成用于比较的键值。keyfunc 是一个函数,接收 sequence 中的单个元素并返回其键值。如果未提供此参数,或 keyfunc 为 nil,则默认使用 identity;即直接将元素本身作为排序键。
:lessp predicate使用 predicate 对键进行排序。predicate 是一个接收两个排序键作为参数的函数,若第一个键应排在第二个之前,则返回非 nil。如果未提供此参数,或 predicate 为 nil,则使用 value<。该函数适用于多种 Lisp 类型,通常按升序排序(see definition of value<,见下文)。
为保证一致性,所有谓词必须遵守以下规则:
:reverse flag如果 flag 为非 nil,则反转排序顺序。在默认 :lessp 谓词下,这表示按降序排序。
:in-place flag如果 flag 为非 nil,则对 sequence 进行原地排序(破坏性排序)并返回该序列。如果为 nil 或未提供此参数,则返回输入序列的排序副本,sequence 本身保持不变。原地排序速度稍快,但会丢失原序列。
如果默认行为不符合你的需求,通常提供一个新的 :key 函数,会比改用另一个 :lessp 谓词更简单、更高效。例如,考虑对这些字符串进行排序:
(setq numbers '("one" "two" "three" "four" "five" "six"))
(sort numbers)
⇒ ("five" "four" "one" "six" "three" "two")
你可以通过提供一个不同的键函数,转而按长度对这些字符串进行排序:
(sort numbers :key #'length)
⇒ ("one" "two" "six" "four" "five" "three")
请注意,得益于排序的稳定性,长度相同的字符串会保留其原始顺序。现在假设你想要按长度排序,但在长度相同时(出现并列时),再根据字符串内容来打破平局。最简单的方法是指定一个键函数,该函数能将元素转换为可按此规则排序的值。由于 value< 会按字典序对复合对象(点对、列表、向量和记录)进行排序,你可以这样做:
(sort numbers :key (lambda (x) (cons (length x) x)))
⇒ ("one" "six" "two" "five" "four" "three")
这是因为 (3 . "six") 排在 (3 . "two") 之前,依此类推。
为兼容旧版本 Emacs,sort 函数也支持以固定的双参数形式调用:
(sort sequence predicate)
其中 predicate 对应前述 :lessp 参数。使用该形式调用时,排序始终以原地方式执行。
有关更多执行排序操作的函数,see Sorting Text。关于 sort 函数的实用示例,可参见 Access to Documentation Strings 中对 documentation 函数的说明。
该函数会在 a 按标准排序规则应排在 b 之前时返回非 nil 值;这意味着,若 b 排在 a 之前、二者相等或无排序关系,函数会返回 nil。
参数 a 和 b 必须为同一类型。具体规则如下:
< 进行比较(see definition of <)。
string-lessp 进行比较(see definition of string-lessp),符号则通过将其名称作为字符串比较来排序。
value< 比较后的结果。若其中一个序列先遍历完所有元素,则较短的序列排在较长的序列之前。
nil)会排在所有有效缓冲区之前。
nil。
Examples:
(value< -4 3.5) ⇒ t (value< "dog" "cat") ⇒ nil (value< 'yip 'yip) ⇒ nil (value< '(3 2) '(3 2 0)) ⇒ t (value< [3 2 "a"] [3 2 "b"]) ⇒ t
需要注意的是,nil 的处理方式取决于其比较对象:它会被视作符号(symbol)或空列表(empty list)二者其一:
(value< nil '(0)) ⇒ t (value< 'nib nil) ⇒ t
可比较的序列(列表、向量等)长度没有限制,但如果使用 value< 比较循环结构或深度嵌套的数据结构,该函数可能会报错并失败。
seq.el 库提供了以下额外的序列操作宏和函数,均以 seq- 为前缀。
本库中定义的所有函数都无副作用;也就是说,它们不会修改你传入的任何序列(列表、向量或字符串)。除非另有说明,返回结果的类型与输入序列的类型相同。对于接收判定函数(predicate)的那些函数,该判定函数应是只接受一个参数的函数。
seq.el 库可以进行扩展,以支持更多类型的序列式数据结构。为此,所有函数均通过 cl-defgeneric 定义。有关如何使用 cl-defgeneric 进行扩展的更多细节,see 泛型函数。
该函数返回 sequence 中指定 index 位置的元素。index 为整数,其有效值范围是从 0 到 sequence 长度减 1。对于内置序列类型,若传入超出范围的索引值,seq-elt 的行为与 elt 一致。详细说明参见 Definition of elt。
(seq-elt [1 2 3 4] 2) ⇒ 3
seq-elt 返回的位置可通过 setf 进行赋值(see setf 宏)。
(setq vec [1 2 3 4]) (setf (seq-elt vec 2) 5) vec ⇒ [1 2 5 4]
该函数返回 sequence 中包含的元素个数。对于内置序列类型,seq-length 的行为与 length 一致。See Definition of length。
若 object 是序列(列表或数组),或是通过 seq.el 通用函数定义的其他序列类型,则该函数返回非 nil 值。这是 sequencep 的可扩展变体。
(seqp [1 2]) ⇒ t
(seqp 2) ⇒ nil
该函数返回 sequence 中除前 n 个(n 为整数)元素之外的所有元素。若 n 为负数或零,则返回结果为 sequence 本身。
(seq-drop [1 2 3 4 5 6] 3) ⇒ [4 5 6]
(seq-drop "hello world" -4) ⇒ "hello world"
该函数返回 sequence 的前 n 个(n 为整数)元素。若 n 为负数或零,则返回结果为 nil。
(seq-take '(1 2 3 4) 3) ⇒ (1 2 3)
(seq-take [1 2 3 4] 0) ⇒ []
该函数按顺序返回 sequence 中的元素,在第一个使 predicate 返回 nil 的元素处停止截取(即不包含该元素)。
(seq-take-while (lambda (elt) (> elt 0)) '(1 2 3 -1 -2)) ⇒ (1 2 3)
(seq-take-while (lambda (elt) (> elt 0)) [-1 4 6]) ⇒ []
该函数按顺序返回 sequence 中的元素,从第一个使 predicate 返回 nil 的元素开始截取(包含该元素)。
(seq-drop-while (lambda (elt) (> elt 0)) '(1 2 3 -1 -2)) ⇒ (-1 -2)
(seq-drop-while (lambda (elt) (< elt 0)) [1 4 6]) ⇒ [1 4 6]
该函数返回一个列表,其中包含 sequence 被拆分后的若干子序列,每个子序列的长度最多为 length。(若 sequence 的长度并非 length 的整数倍,则最后一个子序列的长度可能小于 length。)
(seq-split [0 1 2 3 4] 2) ⇒ ([0 1] [2 3] [4])
该函数依次将 function 作用于 sequence 中的每个元素(此举通常是为了利用其副作用),并返回 sequence 本身。
该函数返回将 function 作用于 sequence 中每个元素后得到的结果,返回值为一个列表。
(seq-map #'1+ '(2 4 6)) ⇒ (3 5 7)
(seq-map #'symbol-name [foo bar])
⇒ ("foo" "bar")
该函数会将 function 应用于 sequence 的每个元素及其在 seq 中的索引,并返回应用后的结果。返回值为一个列表。
(seq-map-indexed (lambda (elt idx)
(list idx elt))
'(a b c))
⇒ ((0 a) (1 b) (2 c))
该函数会将 function 应用于 sequences 中的每组对应元素,并返回应用后的结果。function 的参数个数(参见 see subr-arity)必须与序列的数量相匹配。映射过程会在最短的序列遍历完毕时终止,返回值为一个列表。
(seq-mapn #'+ '(2 4 6) '(20 40 60)) ⇒ (22 44 66)
(seq-mapn #'concat '("moskito" "bite") ["bee" "sting"])
⇒ ("moskitobee" "bitesting")
该函数返回 sequence 中所有使 predicate 返回非 nil 值的元素组成的列表。
(seq-filter (lambda (elt) (> elt 0)) [1 -1 3 -3 5]) ⇒ (1 3 5)
(seq-filter (lambda (elt) (> elt 0)) '(-1 -3 -5)) ⇒ nil
该函数返回 sequence 中所有使 predicate 返回 nil 值的元素组成的列表。
(seq-remove (lambda (elt) (> elt 0)) [1 -1 3 -3 5]) ⇒ (-1 -3)
(seq-remove (lambda (elt) (< elt 0)) '(-1 -3 -5)) ⇒ nil
该函数返回 sequence 的一个副本,其中位于(从零开始计数的)索引 n 处的元素已被移除。返回结果的序列类型与 sequence 保持一致。
(seq-remove-at-position [1 -1 3 -3 5] 0) ⇒ [-1 3 -3 5]
(seq-remove-at-position [1 -1 3 -3 5] 3) ⇒ [1 -1 3 5]
该函数返回一个列表,包含对 sequence 中的每个元素调用 function 后得到的所有非 nil 结果。
(seq-keep #'cl-digit-char-p '(?6 ?a ?7)) ⇒ (6 7)
该函数的执行逻辑为:首先以 initial-value 和 sequence 的第一个元素为参数调用 function,接着以上一次调用的结果和 sequence 的第二个元素为参数调用 function,然后再以上一轮结果和 sequence 的第三个元素为参数调用 function,依此类推,最终返回最后一次调用 function 的结果。function 需为接收两个参数的函数。
调用 function 时会传入两个参数:initial-value(后续则为累计值)作为第一个参数,sequence 中的元素依次作为第二个参数。
若 sequence 为空序列,则不会调用 function,直接返回 initial-value。
(seq-reduce #'+ [1 2 3 4] 0) ⇒ 10
(seq-reduce #'+ '(1 2 3 4) 5) ⇒ 15
(seq-reduce #'+ '() 3) ⇒ 3
该函数会依次将 predicate 应用于 sequence 的每个元素,并返回第一个由该断言函数返回的非 nil 值。
(seq-some #'numberp ["abc" 1 nil]) ⇒ t
(seq-some #'numberp ["abc" "def"]) ⇒ nil
(seq-some #'null ["abc" 1 nil]) ⇒ t
(seq-some #'1+ [2 4 6]) ⇒ 3
该函数返回 sequence 中首个使 predicate 返回非 nil 值的元素。若没有元素匹配该断言函数,则返回 default。
需注意,若找到的元素与 default 的值完全相同,此函数会存在二义性 —— 这种情况下无法判断究竟是找到了匹配元素,还是根本没有找到任何匹配元素。
(seq-find #'numberp ["abc" 1 nil]) ⇒ 1
(seq-find #'numberp ["abc" "def"]) ⇒ nil
若将 predicate 应用于 sequence 的每一个元素后,返回结果均为非 nil 值,则该函数返回非 nil 值。
(seq-every-p #'numberp [2 4 6]) ⇒ t
(seq-every-p #'numberp [2 4 "6"]) ⇒ nil
若 sequence 为空序列,则该函数返回非 nil 值。
(seq-empty-p "not empty") ⇒ nil
(seq-empty-p "") ⇒ t
该函数返回 sequence 中使 predicate 返回非 nil 值的元素数量。
(seq-count (lambda (elt) (> elt 0)) [-1 2 0 3 -2]) ⇒ 2
该函数返回 sequence 的一个副本,该副本会根据 function 进行排序。其中 function 是一个接收两个参数的函数:若第一个参数应排在第二个参数之前,该函数需返回非 nil 值。
该函数与 seq-sort 功能类似,但在排序前,会先对 sequence 中的每个元素应用 function 进行转换。function 是一个接收单个参数的函数。
(seq-sort-by #'seq-length #'> ["a" "ab" "abc"]) ⇒ ["abc" "ab" "a"]
若 sequence 中至少有一个元素与 elt 相等,则该函数返回非 nil 值。若可选参数 function 的值为非 nil,则会使用这个接收两个参数的函数来替代默认的 equal 函数进行比较。
(seq-contains-p '(symbol1 symbol2) 'symbol1) ⇒ t
(seq-contains-p '(symbol1 symbol2) 'symbol3) ⇒ nil
该函数用于检查 sequence1 和 sequence2 是否包含完全相同的元素(元素顺序不影响判断结果)。若可选参数 testfn 的值为非 nil,则会使用这个接收两个参数的函数,替代默认的 equal 函数进行元素比较。
(seq-set-equal-p '(a b c) '(c b a)) ⇒ t
(seq-set-equal-p '(a b c) '(c b)) ⇒ nil
(seq-set-equal-p '("a" "b" "c") '("c" "b" "a"))
⇒ t
(seq-set-equal-p '("a" "b" "c") '("c" "b" "a") #'eq)
⇒ nil
该函数返回 sequence 中首个与 elt 相等的元素的(从零开始计数的)索引值。若可选参数 function 的值为非 nil,则会使用这个接收两个参数的函数,替代默认的 equal 函数进行元素比较。
(seq-position '(a b c) 'b) ⇒ 1
(seq-position '(a b c) 'd) ⇒ nil
该函数返回一个列表,其中包含 sequence 中满足以下条件的所有元素的(从零开始计数的)索引:将元素与 elt 作为参数传入 testfn 时,该函数返回非 nil 值。testfn 的默认值为 equal 函数。
(seq-positions '(a b c a d) 'a) ⇒ (0 3)
(seq-positions '(a b c a d) 'z) ⇒ nil
(seq-positions '(11 5 7 12 9 15) 10 #'>=) ⇒ (0 3 5)
该函数返回 sequence 去除重复元素后的元素组成的列表。若可选参数 function 的值为非 nil,则会使用这个接收两个参数的函数,替代默认的 equal 函数来判定元素是否重复。
(seq-uniq '(1 2 2 1 3)) ⇒ (1 2 3)
(seq-uniq '(1 2 2.0 1.0) #'=) ⇒ (1 2)
该函数返回 sequence 中从 start 到 end(均为整数)的子序列(end 的默认值为序列最后一个元素的位置)。若 start 或 end 为负数,则从 sequence 的末尾开始计数。
(seq-subseq '(1 2 3 4 5) 1) ⇒ (2 3 4 5)
(seq-subseq '[1 2 3 4 5] 1 3) ⇒ [2 3]
(seq-subseq '[1 2 3 4 5] -3 -1) ⇒ [3 4]
该函数返回一个类型为 type 的序列,该序列由 sequences 中的所有序列拼接而成。type 的可选值为:vector(向量)、list(列表)或 string(字符串)。
(seq-concatenate 'list '(1 2) '(3 4) [5 6]) ⇒ (1 2 3 4 5 6)
(seq-concatenate 'string "Hello " "world") ⇒ "Hello world"
该函数的执行逻辑为:先将 function 应用于 sequence 的每个元素并得到结果,再对该结果调用 seq-concatenate 函数,最终返回此次调用的结果。返回值为类型为 type 的序列;若 type 的值为 nil,则返回列表。
(seq-mapcat #'seq-reverse '((3 2 1) (6 5 4))) ⇒ (1 2 3 4 5 6)
该函数返回一个列表,其中包含将 sequence 的元素按长度 n 分组后得到的子序列。最后一个子序列包含的元素数量可能少于 n。n 必须为整数;若 n 为负整数或 0,则返回值为 nil。
(seq-partition '(0 1 2 3 4 5 6 7) 3) ⇒ ((0 1 2) (3 4 5) (6 7))
该函数返回一个列表,其中包含所有出现在 sequence1 或 sequence2 中的元素。返回列表中的所有元素均为唯一值(即列表中任意两个元素经比较后都不会判定为相等)。若可选参数 function 的值为非 nil,则应使用这个接收两个参数的函数来比较元素,以替代默认的 equal 函数。
(seq-union [1 2 3] [3 5]) ⇒ (1 2 3 5)
该函数返回一个列表,其中包含所有同时出现在 sequence1 和 sequence2 中的元素。若可选参数 function 的值为非 nil,则会使用这个接收两个参数的函数来比较元素,以替代默认的 equal 函数。
(seq-intersection [2 3 4 5] [1 3 5 6 7]) ⇒ (3 5)
该函数返回一个列表,其中包含所有出现在 sequence1 中但未出现在 sequence2 中的元素。若可选参数 function 的值为非 nil,则会使用这个接收两个参数的函数来比较元素,以替代默认的 equal 函数。
(seq-difference '(2 3 4 5) [1 3 5 6 7]) ⇒ (2 4)
该函数将 sequence 中的元素分组为一个关联列表(alist),该列表的键(key)是对 sequence 中的每个元素应用 function 后得到的结果。键的比较采用 equal 函数进行。
(seq-group-by #'integerp '(1 2.1 3 2 3.2)) ⇒ ((t 1 3 2) (nil 2.1 3.2))
(seq-group-by #'car '((a 1) (b 2) (a 3) (c 4))) ⇒ ((b (b 2)) (a (a 1) (a 3)) (c (c 4)))
该函数将序列 sequence 转换为类型为 type 的序列。type 可以是以下符号之一:vector(向量)、string(字符串)或 list(列表)。
(seq-into [1 2 3] 'list) ⇒ (1 2 3)
(seq-into nil 'vector) ⇒ []
(seq-into "hello" 'vector) ⇒ [104 101 108 108 111]
该函数返回 sequence(序列)中的最小元素。sequence 中的元素必须为数字或标记(marker,see Markers )。 This function returns the smallest element of sequence. The elements of sequence must be numbers or markers (see Markers).
(seq-min [3 1 2]) ⇒ 1
(seq-min "Hello") ⇒ 72
该函数返回 sequence(序列)中的最大元素。sequence 中的元素必须为数字或标记(marker)。
(seq-max [1 3 2]) ⇒ 3
(seq-max "Hello") ⇒ 111
该宏与 dolist(详见 dolist 章节)的功能类似,不同之处在于 sequence(序列)可以是列表(list)、向量(vector)或字符串(string)类型。该宏主要用于产生副作用(side-effects)场景。
该宏会将 var-sequence(变量序列)中定义的变量,绑定到 val-sequence(值序列)中对应的元素值上。这种操作被称为 解构绑定(destructuring binding)。var-sequence 中的元素本身也可以包含序列,从而支持嵌套解构。
var-sequence 序列中还可以包含 &rest 标记,其后紧跟一个变量名 —— 该变量会被绑定到 val-sequence 中剩余的所有元素上。
(seq-let [first second] [1 2 3 4] (list first second)) ⇒ (1 2)
(seq-let (_ a _ b) '(1 2 3 4) (list a b)) ⇒ (2 4)
(seq-let [a [b [c]]] [1 [2 [3]]] (list a b c)) ⇒ (1 2 3)
(seq-let [a b &rest others] [1 2 3 4] others)
⇒ [3 4]
pcase 模式提供了另一种实现解构绑定的机制,详见 使用 pcase 模式进行解构 章节。
该宏的功能与 seq-let 类似,不同之处在于:它会以 setq 的方式为变量赋值,而非像 let 那样进行变量绑定。
(let ((a nil)
(b nil))
(seq-setq (_ a _ b) '(1 2 3 4))
(list a b))
⇒ (2 4)
该函数随机返回 sequence(序列)中的一个元素。
(seq-random-elt [1 2 3 4]) ⇒ 3 (seq-random-elt [1 2 3 4]) ⇒ 2 (seq-random-elt [1 2 3 4]) ⇒ 4 (seq-random-elt [1 2 3 4]) ⇒ 2 (seq-random-elt [1 2 3 4]) ⇒ 1
若 sequence(序列)为空,则该函数会触发一个错误。