Elisp: Map List/Vector
Map: mapcar
Typical way to go thru a
Sequence
is using mapcar
. Note that it returns a list, even if input is a vector.
(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)
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 (foreach)
If you don't need map to return the sequence, use mapc
.
mapc
is like mapcar
, but returns nil.
;; apply a file processing function to a list of files (mapc 'my-update-html-footer (list "~/file1.html" "~/file2.html" "~/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
Loop Thru a List (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.
Loop Fixed Number of Times (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"