Emacs Lisp: List
Emacs Lisp's list datatype is an ordered sequence of things. It is known as linked list data structure in computer science. It is an efficient datatype for stack data structure. (like a stack of books, allowing adding or removing one item at a time from the top in an efficient way.)
Lisp list are made up of lower structure called cons
, as nested Cons Pair.
Any item can be of any type.
Algorithm properties of lisp list:
- Fast and constant time to get value of first element. (by
car
) - Fast and constant time to get rest of list (i.e. without first item). (by
cdr
) - Fast and constant time to add one item to the front (beginning of list). (known as
push
) - Fast and constant time to remove the first element. (known as
pop
) - Any operation for nth element, its time is proportional to size of n.
Create List (Literal Expression)
To create a list, write it like this (list a b etc)
.
(list args)
-
create a list of items.
; assign a list to a var (setq xx (list 1 "b" 3))
; prints a list (message "%S" xx)
If you do not want the elements evaluated, write it like this:
'(a b etc)
This is equivalent to
(quote (a b etc))
; assign a list to a var (setq xx '(a b c)) ; prints a list (message "%S" xx)
;; create a list of values of variables (let ((x 3) (y 4) (z 5)) (message "%S" (list x y z)) ) ; prints "(3 4 5)"
Empty List, nil
In elisp, empty list is equivalent to nil. The following are all equivalent.
'()
(list)
- nil
(eq '() (list ) ) ; t (eq '() nil); t (eq (list ) nil ) ; t
[see Emacs Lisp: Test Equality]
Create List of Same Value
(make-list LENGTH INIT)
- Create a list of length LENGTH, and all elements with value INIT.
(equal (make-list 3 0) '(0 0 0))
Create List of Range of Numbers
(number-sequence n)
- Return a list of 1 element of value n.
;; just 1 element (equal (number-sequence 5) '(5))
(number-sequence n m)
- return a list from n to m.
;; n to m, inclusive (equal (number-sequence 2 5) '(2 3 4 5))
(number-sequence n m step)
- Return a list of a range of numbers, from n to m, in increment of step.
;; using 3 as step (equal (number-sequence 0 9 3) '(0 3 6 9)) (equal (number-sequence 0 9 2) '(0 2 4 6 8)) ;; ending item dropped ;; negative step (equal (number-sequence 4 0 -1) '(4 3 2 1 0)) ;; boundaries can be float but will not include (equal (number-sequence 2.2 5.3) '(2.2 3.2 4.2 5.2))
Length
(length SEQUENCE)
- return count of elements.
(equal (length '("a" "b" "c") ) 3)
Get Element from List
(car list)
- first element
(equal (car '("a" "b" "c")) "a" )
(cdr list)
- rest elements
(equal (cdr '(0 1 2 3 4)) '(1 2 3 4))
(nth n list)
- nth element.
(Index starts from 0.)
(equal (nth 1 '(0 1 2 3 4)) 1)
(nthcdr n list)
- rest starting at n.
(equal (nthcdr 2 '(0 1 2 3 4)) '(2 3 4))
(last list)
- last as a list. i.e. return
(cons lastElement nil)
.To get the actual last item of a list, do
(car (last list))
(equal (car (last (list "a" "b" "c"))) "c" ) (equal (last (list "a" "b" "c")) (cons "c" nil) )
(last list &optional n)
- last n items.
(equal (last '(0 1 2 3 4 5 6) 2) '(5 6) )
(butlast list n)
- without the last n elements.
(equal (butlast '(0 1 2 3 4 5)) '(0 1 2 3 4)) (equal (butlast '(0 1 2 3 4 5) 2) '(0 1 2 3))
Add to List
(cons new list)
- Return a new list, with new added to front. (prepend)
(equal (cons "a" '("c" "d")) '("a" "c" "d")) (equal (cons '("a" "b") '("c" "d")) '(("a" "b") "c" "d"))
(add-to-list LIST-VAR ELEMENT &optional APPEND COMPARE-FN)
- Add to list when not already in it.
(setq xx '(1 2 3)) ;; add "a" to it. return the modified var (eq (add-to-list 'xx "a" ) xx) ;; check the new value (equal xx '("a" 1 2 3))
(add-to-ordered-list LIST-VAR ELEMENT &optional ORDER)
- Add to specific position in list, if it does not exist. The list is reordered.
Modify List Variable
The following are designed to modify a list variable in-place.
(push new listVar)
-
- Add element to the front.
- Modify the listVar.
- Return the new value of listVar
(setq xx '(1)) ;; after push, the var is modified, and the var's new value is returned (eq (push 2 xx) xx) (equal xx '(2 1))
The variable is modified even if the pushed list is inside a list.
;; a list of lists (setq xx '((1 2) (3 4) (5 6))) ;; push b to one of the list (equal (push "b" (nth 1 xx)) '("b" 3 4)) ;; the xx is modified (equal xx '((1 2) ("b" 3 4) (5 6)))
also if the variable is a vector:
;; a vector of lists (setq xx [(1 2) (3 4) (5 6)]) ;; push b to one of the list (equal (push "b" (aref xx 1)) '("b" 3 4 )) ;; the xx is modified (equal xx [(1 2) ("b" 3 4 ) (5 6)] )
(pop listVar)
- Remove first element from the variable. Return the removed element.
(setq xx '(1 2 3 4)) (equal (pop xx) 1) (equal xx '(2 3 4))
(nbutlast listVar n)
- Remove last n elements from the variable. Return the new value of the variable.
(setq xx '(0 1 2 3)) (equal (nbutlast xx 1) '(0 1 2)) (equal xx '(0 1 2))
(setcar listVar new)
- Replace the first element in listVar with new. Return new.
(setq xx '(1 2 3 4)) (equal (setcar xx "a") "a") (equal xx '("a" 2 3 4))
(setcdr listVar newTail)
- Replace the rest of elements in listVar with newTail. Return newTail.
Warning: if you want the result to be a Proper List, the newTail should be a proper list.
(setq xx '(1 2 3 4)) (equal (setcdr xx (cons "a" nil)) (cons "a" nil)) (equal xx '(1 "a"))