Elisp: Map / Loop Thru List / Vector

By Xah Lee. Date: . Last updated: .

Map: mapcar

Typical way to go thru a sequence is using mapcar. Note that it returns a list, even if input is a vector. 〔►see Elisp: Sequence: List, Array

(mapcar FUNCTION SEQUENCE) → Apply FUNCTION to each element of SEQUENCE, and make a list of the results. The result is a list, with same length as SEQUENCE. SEQUENCE may be a list, a vector, a bool-vector, or a string.

;; add 1 to each vector element
(mapcar '1+ [3 4 5] ) ; (4 5 6)
;; add one to each list element
(mapcar '1+ '(3 4 5)) ; (4 5 6)

1+ is a lisp function. It adds 1 to argument and returns it. For example, (1+ 2) returns 3.

To use a function in mapcar, you need to quote the function's name.

1+ is a function, so we quote it and have '1+ or (quote 1+)

Here's another example.

; take the 1st element of each
(mapcar 'car '((1 2) (3 4) (5 6))) ; (1 3 5)

list and vector are sequence

In emacs lisp, list and vector types are both considered sequences.

Many functions work with sequences. (that is, argument can be list or vector)

〔►see Elisp: Sequence: List, Array

mapcar with lambda

mapcar is most commonly used with lambda. Here's a example:

;; get first element of each row
(mapcar
 (lambda (x) (elt x 0))
 [[1 2] [3 4]] ) ; ⇒ (1 3)

lambda means function, often known as “anonymous function”. It let you define a function in the middle of your code.

The form is (lambda (args) body).

For example, (lambda (x y) (+ x y)) is a function that takes two arguments, x and y, and returns their sum.

More examples with lambda:

; add one to each list member
(mapcar
 (lambda (x) (+ x 1))
 (list 1 2 3 4)
) ; (2 3 4 5)
;; take the 2nd element of each
(mapcar (lambda (x) (nth 1 x))
        '((1 2) (3 4) (5 6))) ; (2 4 6)

mapc

If you don't need map to return the sequence, use mapc.

mapc → like mapcar, but returns nil.

;; apply a file processing function to a list of files
(mapc 'my-update-html-footer
      (list
       "~/web/file1.html"
       "~/web/file2.html"
       "~/web/file3.html"
       ))
;; example of mapc on vector
(mapc
 (lambda (x)
   (insert (number-to-string (aref x 0))))
 [[1 2] [3 4]] )

;; insert first element of each row into buffer
;; (it inserts 13)
;; returns nil

dolist

(dolist (VAR LIST) BODY) → Loop over a list. Evaluate BODY with VAR bound to each element from LIST, returns nil.

(dolist (VAR LIST RESULT) BODY) → returns RESULT.

(let (
      (xlist (number-sequence 97 122)) ;; list 97 to 122
      )
  (dolist (n xlist) (insert n)))

;; inserts
;; abcdefghijklmnopqrstuvwxyz

The major difference between dolist and mapc is that dolist uses expression, mapc uses a function. Also, dolist work with list only, mapc works with list and vectors.

dotimes

dotimes is useful when you want to go thru a list by a increasing index.

(dotimes (VAR COUNT) BODY …) → Loop a certain number of times. Evaluate BODY with VAR bound to successive integers running from 0, inclusive, to COUNT, exclusive. Returns nil

(dotimes (VAR COUNT RESULT) BODY …) → After loop, evaluate RESULT to get the return value.

(dotimes (i 4)
  (insert (number-to-string i)))
;; inserts "0123", returns nil
(let ((v [3 4 5]))
  (dotimes (i (length v))
    (insert
     (number-to-string
      (elt v i))))) ; inserts 345

while Loop

Another common form to loop thru a list is using the while function. In each iteration, pop is used to reduce the list.

(let ((mylist '(a b c)))
  (while mylist
    (message "%s" (pop mylist))
    (sleep-for 1)))

Example with vector:

(setq v [3 4 5])
(setq i 0)

(while (< i (length v))
  (insert (format "%d" (elt v i)))
  (setq i (1+ i))) ; inserts "345"

Exit Loop/Function, catch/throw

Elisp: Exit Loop/Function, catch/throw

Data Structure Topic

  1. Elisp: Sequence: List, Array
  2. Elisp: Vector
  3. Elisp: List
  4. Elisp: Association List
  5. Elisp: Property List
  6. Elisp: Symbol Property List
  7. Elisp: Map / Loop Thru List / Vector
  8. Elisp: Filter a List
  9. Elisp: Hash Table
Liket it? Put $5 at patreon. Or Buy Xah Emacs Tutorial. Thanks.