Skip to content

LISP - 映射序列元素

Lisp 的核心优势之一是它对函数式编程的支持。序列 (sequence) 是一种有序的元素集合,Common Lisp 为其提供了强大的抽象,涵盖了列表 (list) 和向量 (vector) 两种类型。映射 (mapping) 是将一个函数应用于序列中的每个元素,以创建一个新序列的过程。

mapcar 是针对列表的经典映射函数。它接受一个函数和一个或多个列表作为参数。mapcar 会将该函数应用于列表中对应位置的元素,并返回一个包含结果的新列表。

示例:对列表中的每个数字求平方

Section titled “示例:对列表中的每个数字求平方”
;; #’ 语法是 (function ...) 的简写形式。
;; 它获取与符号或 lambda 表达式关联的函数对象。
(mapcar #'(lambda (x) (* x x))
'(1 2 3 4 5))
(1 4 9 16 25)
(mapcar #'+ '(1 2 3) '(10 20 30))
(11 22 33)

map 是一个更通用的映射函数。它的第一个参数指定了要返回的序列类型。这使得你可以对列表、向量或字符串进行映射,并生成任何类型的序列作为结果。

示例:将字符串转换为字符向量

Section titled “示例:将字符串转换为字符向量”
;; identity 函数仅返回其参数。
(map 'vector #'identity "Lisp")
#(#\L #\i #\s #\p)
(map 'string #'char-upcase "tutorialspoint")
"TUTORIALSPOINT"

对于更复杂的迭代,loop 宏是 Common Lisp 中一个极其强大且地道的工具。它提供了一种迷你语言,以声明式风格表达循环。

(loop for x in '(1 2 3 4 5)
collect (* x x))
(1 4 9 16 25)
  • mapcar:适用于对一个或多个列表进行简单、函数式转换,且结果始终为列表的情况。它为此目的提供了清晰且高度表达性的方式。
  • map:当你需要结果为特定序列类型(如向量或字符串)时使用,或者当你根本不需要结果时(此时可以使用 (map nil ...) 来实现副作用)。
  • loop:适用于更复杂的场景。例如,当你需要同时进行过滤和映射、迭代不同的数据结构(如哈希表),或需要对迭代进行细粒度控制时。