LISP - 在列表上使用 `mapcar`
使用 mapcar 进行函数式列表处理
Section titled “使用 mapcar 进行函数式列表处理”在 Common Lisp 中,mapcar 是函数式编程风格的基石。它提供了一种简洁优雅的方式,将函数应用于一个或多个列表的每个元素,生成一个包含结果的新列表。它是非破坏性的,这意味着原始列表永远不会被修改。
语法和核心思想
Section titled “语法和核心思想”(mapcar function list &rest more-lists)function:要应用的函数。它必须接受与提供给mapcar的列表数量相同数量的参数。list&more-lists:一个或多个要处理的列表。
mapcar 的工作方式是:从每个列表中取出第一个元素,将其传递给函数,并收集结果。然后对第二个元素、第三个元素等重复此操作,直到达到最短列表的末尾。
示例 1:单个列表上的基本操作
Section titled “示例 1:单个列表上的基本操作”最简单的用例是转换单个列表。
;; 让我们定义一个数字列表(defvar *my-numbers* '(1 2 3 4 5))
;; 使用命名函数:将每个数字递增;; #'1+ 是 (function 1+) 的简写(print (mapcar #'1+ *my-numbers*))
;; 使用 lambda 函数:平方每个数字(print (mapcar (lambda (n) (* n n)) *my-numbers*))(2 3 4 5 6)(1 4 9 16 25)示例 2:同时处理多个列表
Section titled “示例 2:同时处理多个列表”这就是 mapcar 真正发挥作用的地方。它可以并行处理多个列表。
;; 将两个列表的对应元素相加(print (mapcar #'+ '(1 2 3) ; #'+ 的第一个参数 '(10 20 30))) ; #'+ 的第二个参数
;; 当最短的列表耗尽时停止(print (mapcar #'+ '(1 2) ; 最短的列表 '(10 20 30)))(11 22 33)(11 22)示例 3:使用字符串和其他数据类型
Section titled “示例 3:使用字符串和其他数据类型”mapcar 不仅限于数字。它可以操作任何数据类型。
;; 让我们将函数应用于字符串列表(defvar *words* '("Welcome" "To" "Modern" "Lisp"))
;; 获取每个单词的长度(print (mapcar #'length *words*))
;; 将每个单词转换为小写(print (mapcar #'string-downcase *words*))(7 2 6 4)("welcome" "to" "modern" "lisp")选择正确的映射函数
Section titled “选择正确的映射函数”Lisp 提供了几种映射函数。选择正确的函数可以提高代码清晰度。
mapcar:当您想根据应用函数的结果创建一个新列表时使用。这是最常见的情况。mapc:当您需要为副作用(例如,打印、修改哈希表)调用函数,并且您不需要结果时使用。它返回其第一个列表参数。map:一个更通用的函数。它可以生成指定类型的序列(例如,向量而不是列表)。(map 'vector #'1+ '(1 2 3))返回#(2 3 4)。maplist:当您的函数需要操作列表的连续子列表(cdrs)而不仅仅是元素时使用。
针对您的任务使用最具体的函数。如果您正在将列表转换为新列表,mapcar 是惯用的选择。如果您只是打印每个元素,mapc 更高效,并且更清晰地表明了您的意图。
;; 使用 mapc 进行副作用操作(打印)(mapc (lambda (word) (format t "~a " word)) *words*);; 输出:Welcome To Modern Lisp