Skip to content

LISP - Using mapcar on List

In Common Lisp, mapcar is a cornerstone of the functional programming style. It provides a concise and elegant way to apply a function to each element of one or more lists, producing a new list containing the results. It is non-destructive, meaning the original lists are never modified.

(mapcar function list &rest more-lists)
  • function: The function to apply. It must accept as many arguments as there are lists provided to mapcar.
  • list & more-lists: One or more lists to be processed.

mapcar works by taking the first element from each list, passing them to the function, and collecting the result. It then repeats this for the second elements, third elements, and so on, until it reaches the end of the shortest list.

Example 1: Basic Operations on a Single List

Section titled “Example 1: Basic Operations on a Single List”

The simplest use case is transforming a single list.

;; Let's define a list of numbers
(defvar *my-numbers* '(1 2 3 4 5))
;; Using a named function: increment each number
;; #'1+ is a shorthand for (function 1+)
(print (mapcar #'1+ *my-numbers*))
;; Using a lambda function: square each number
(print (mapcar (lambda (n) (* n n)) *my-numbers*))
(2 3 4 5 6)
(1 4 9 16 25)

Example 2: Processing Multiple Lists Together

Section titled “Example 2: Processing Multiple Lists Together”

This is where mapcar truly shines. It can process multiple lists in parallel.

;; Add corresponding elements from two lists
(print (mapcar #'+
'(1 2 3) ; First argument to #'+
'(10 20 30))) ; Second argument to #'+
;; It stops when the shortest list runs out
(print (mapcar #'+
'(1 2) ; Shortest list
'(10 20 30)))
(11 22 33)
(11 22)

Example 3: Working with Strings and Other Data Types

Section titled “Example 3: Working with Strings and Other Data Types”

mapcar is not limited to numbers. It can operate on any data type.

;; Let's apply a function to a list of strings
(defvar *words* '("Welcome" "To" "Modern" "Lisp"))
;; Get the length of each word
(print (mapcar #'length *words*))
;; Convert each word to lowercase
(print (mapcar #'string-downcase *words*))
(7 2 6 4)
("welcome" "to" "modern" "lisp")

Lisp provides several mapping functions. Choosing the right one improves code clarity.

  • mapcar: Use when you want to create a new list from the results of applying a function. This is the most common case.
  • mapc: Use when you need to call a function for its side effects (e.g., printing, modifying a hash table) and you don’t need the results. It returns its first list argument.
  • map: A more general function. It can produce a sequence of a specified type (e.g., a vector instead of a list). (map 'vector #'1+ '(1 2 3)) returns #(2 3 4).
  • maplist: Use when your function needs to operate on the successive sublists (the cdrs) of a list, not just the elements.

Use the most specific function for your task. If you are transforming a list into a new list, mapcar is the idiomatic choice. If you are just printing each element, mapc is more efficient and signals your intent more clearly.

;; Using mapc for side-effects (printing)
(mapc (lambda (word) (format t "~a " word)) *words*)
;; Output: Welcome To Modern Lisp