LISP - 在列表上使用 `mapc`
Lisp - 使用 mapc 进行副作用迭代
Section titled “Lisp - 使用 mapc 进行副作用迭代”Common Lisp 提供了一系列强大的 map 函数,用于迭代序列。虽然 mapcar 用于通过对每个元素应用函数来创建新列表,但 mapc 纯粹用于其副作用。它对每个元素应用函数,但会丢弃结果,始终返回原始列表。
语法和核心区别
Section titled “语法和核心区别”(mapc function list &rest more-lists)function:应用于每个元素的函数。这可以是一个命名函数(例如#'print)或一个lambda函数。list:要迭代的列表。- 返回值:
mapc返回其第一个列表参数。函数调用的返回值被忽略。
需要记住的关键区别:
mapcar(car 用于 ‘c’ontents):收集结果。当您想要将一个列表转换为新列表时使用它。mapc(c 用于 ‘c’onditional/side-effect):丢弃结果。当您想要对每个元素做一些事情时使用它,例如打印、修改文件或更新另一个数据结构。
何时使用 mapc
Section titled “何时使用 mapc”示例:打印到控制台
Section titled “示例:打印到控制台”打印是一个经典的副作用。由于我们不需要收集任何结果,mapc 是一个完美的搭配。
;; Prints each number on a new line(mapc #'print '(10 20 30))102030请注意,REPL 也会打印 mapc 的返回值,即原始列表 (10 20 30)。
示例:修改外部状态
Section titled “示例:修改外部状态”在这里,我们使用 mapc 迭代数字列表并将它们添加到运行总和中。修改 total 是副作用。注意特殊(全局)变量的 *earmuffs* 命名约定。
(defvar *total* 0 "A running total, for demonstration.")
(defun add-to-total (numbers) (mapc (lambda (x) (incf *total* x)) numbers) ;; mapc returns the original list, but we are interested in the final total. *total*)
;; Reset total and run the function(setf *total* 0)(add-to-total '(1 2 3 4 5))15使用 mapc 处理多个列表
Section titled “使用 mapc 处理多个列表”就像 mapcar 一样,mapc 可以同时操作多个列表。提供的函数必须接受与列表数量相等的参数。一旦最短的列表耗尽,迭代就会停止。
(let ((users '("Alice" "Bob" "Charlie")) (ids '(101 102 103))) (mapc (lambda (user-name user-id) (format t "Processing user: ~a (ID: ~a)~%" user-name user-id)) users ids))Processing user: Alice (ID: 101)Processing user: Bob (ID: 102)Processing user: Charlie (ID: 103)替代方案:dolist
Section titled “替代方案:dolist”对于具有副作用的简单循环,dolist 宏通常更具可读性,并且是 mapc 的一个非常常见的替代方案。
;; Using mapc(mapc #'print '(a b c))
;; Using dolist - often considered more direct and clearer(dolist (item '(a b c)) (print item))对于简单的单列表迭代,选择 dolist。当您想要更函数式的风格或需要并行迭代多个列表时,选择 mapc。