LISP - Using mapc on List
Lisp - Iterating for Side Effects with mapc
Section titled “Lisp - Iterating for Side Effects with mapc”Common Lisp provides a family of powerful map functions for iterating over sequences. While mapcar is used to create a new list by applying a function to each element, mapc is used purely for its side effects. It applies a function to each element but discards the results, always returning the original list.
Syntax and Core Distinction
Section titled “Syntax and Core Distinction”(mapc function list &rest more-lists)function: The function to apply to each element. This can be a named function (e.g.,#'print) or alambdafunction.list: The list(s) to iterate over.- Return Value:
mapcreturns its first list argument. The return values of the function calls are ignored.
The key difference to remember:
mapcar(car for ‘c’ontents): Collects results. Use it when you want to transform a list into a new one.mapc(c for ‘c’onditional/side-effect): Discards results. Use it when you want to do something with each element, like printing, modifying a file, or updating another data structure.
When to Use mapc
Section titled “When to Use mapc”Example: Printing to the Console
Section titled “Example: Printing to the Console”Printing is a classic side effect. Since we don’t need to collect any results, mapc is a perfect fit.
;; Prints each number on a new line(mapc #'print '(10 20 30))Output
Section titled “Output”102030Note that the REPL will also print the return value of mapc, which is the original list (10 20 30).
Example: Modifying an External State
Section titled “Example: Modifying an External State”Here, we use mapc to iterate over a list of numbers and add them to a running total. Modifying total is the side effect. Note the *earmuffs* convention for special (global) variables.
(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))Output
Section titled “Output”15Using mapc with Multiple Lists
Section titled “Using mapc with Multiple Lists”Just like mapcar, mapc can operate on multiple lists simultaneously. The provided function must accept a number of arguments equal to the number of lists. Iteration stops as soon as the shortest list is exhausted.
(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))Output
Section titled “Output”Processing user: Alice (ID: 101)Processing user: Bob (ID: 102)Processing user: Charlie (ID: 103)Alternative: dolist
Section titled “Alternative: dolist”For simple loops with side effects, the dolist macro is often more readable and is a very common alternative to mapc.
;; Using mapc(mapc #'print '(a b c))
;; Using dolist - often considered more direct and clearer(dolist (item '(a b c)) (print item))Choose dolist for simple, single-list iteration. Choose mapc when you want a more functional style or need to iterate over multiple lists in parallel.