Elisp: Map / Loop Thru List / Vector
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.
is a function, so we quote it and have
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)
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).
(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)
If you don't need map to return the sequence, use
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 (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 uses expression,
mapc uses a function.
dolist work with list only,
mapc works with list and vectors.
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
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
Data Structure Topic
Patreon me $5. Ask me question on patreon