List Structures

Set Functions

alexandria:setp object &key test key ⇒ boolean

Test if object is a list containing unique elements.

(setp '(a b c)) ;⇒ T
(setp '(a b b)) ;⇒ NIL
(setp '((10 :a) (10.0 :b)) :key #'car)           ;⇒ T
(setp '((10 :a) (10.0 :b)) :key #'car :test #'=) ;⇒ NIL

subsetp list1 list2 &key key test test-not ⇒ boolean

Test if every element of list1 matches an element in list2.

(subsetp '(c b a) '(a b c d)) ;⇒ T
(subsetp '(a b c d) '(c b a)) ;⇒ NIL

alexandria:set-equal list1 list2 &key test key ⇒ boolean

Test if every element in list1 matches an element in list2, and vice-versa.

(set-equal '(a b c) '(c b a)) ;⇒ T
(set-equal '(a b) '(a b c))   ;⇒ NIL

member item list &key key test test-not ⇒ tail

Similiar to find, but if the item is in the list return the tail, otherwise nil. Functional variants are member-if and member-if-not.

(member 'c '(a b c d))             ;⇒ (C D)
(member-if #'evenp '(1 2 3 4))     ;⇒ (2 3 4)
(member-if-not #'evenp '(1 2 3 4)) ;⇒ (1 2 3 4)

adjoin item list &key key test test-not ⇒ new-list

Add item to list if not already there, otherwise return original list. Use pushnew to modify the original list.

union list1 list2 &key key test test-not ⇒ result-list

To save the result in place, use alexandria:unionf.

(union '(a b c) '(f a d)) ;⇒ (A B C D F)

intersection list1 list2 &key key test test-not ⇒ result-list

Return a list that contains every element in both list1 and list2.

(intersection '(a b c) '(b c d)) ;⇒ (B C)

set-difference list1 list2 &key key test test-not ⇒ result-list

Returns a list of elements of list1 that do not appear in list2.

(set-difference '(a b c e) '(b c d)) ;⇒ (A E)

set-exclusive-or list1 list2 &key key test test-not ⇒ result-list

Returns a list of elements that appear in exactly one of list1 and list2.

(set-exclusive-or '(a b c e) '(b c d)) ;⇒ (A D E)

Tree Functions

Lists of lists.

tree-equal

Compares two trees, equal if structure is same shape and leaves are eql (or :test).

copy-tree tree ⇒ new-tree

Creates a copy of a tree of conses.

subst new old tree &key key test test-not ⇒ new-tree

Make a copy of tree with each subtree or leaf matching old replaced by new, the tree counterpart to substitute. Functional variants are subst-if and subst-if-not, called on each atomic value in the tree. The destructive version is nsubst and variants.

(subst "two" 2 '(1 (1 2) (1 (2 3)))) ;⇒ (1 (1 "two") (1 ("two" 3)))
(subst-if "one" #'(lambda (x) (equal x 1)) '(1 2 (3 2 1))) ;⇒ ("one" 2 (3 2 "one")))

sublis alist tree &key key test test-not ⇒ new-tree

Make a tree copy and substitute multiple leaves using an alist.

(sublis '((1 . "one") (2 . "two")) '(1 (1 2) (1 (2 3))))
  ;⇒ ("one" ("one" "two") ("one" ("two" 3))))

alexandria:flatten tree ⇒ list

Collect non-null leaves into a list.

(flatten '(1 2 (3 2 1) ((1 1 nil) (2 2)))) ;⇒ (1 2 3 2 1 1 1 2 2)

alexandria:circular-tree-p object ⇒ boolean

Test if object is a circular tree.

Property List (plist)

Lists with alternating keys and values: (:x 10 :y 20). Uses #'eq for :test, so should only use symbols as keywords.

Every symbol contains metadata on it stored as a plist:

(symbol-plist 'symbol) ;access plist of symbol
(get 'symbol 'key) ;equivalent to (getf (symbol-plist 'symbol)
(setf (get 'symbol :my-key) "information") ;set value
(remprop 'symbol 'my-key) ;remove property, same as (remf (symbol-plist 'symbol) 'my-key)

getf plist indicator &optional default ⇒ value

(getf plist :x)           ;⇒ 10
(setf (getf plist :x) 30) ;⇒ 30

remf place indicator ⇒ boolean

(remf plist :x) ;⇒ T

get-properties plist indicator-list ⇒ indicator, value, tail

Used since getf can’t distinguish an absent property from nil. Returns on the first key found.

(get-properties plist '(:x :y)) ;⇒ :X, 10, (:X 10 :Y 20)

alexandria:plist-alist plist

alexandria:plist-hash-table plist &rest hash-table-initargs

alexandria:remove-from-plist plist &rest keys

alexandria:remove-from-plistf plist &rest keys

destructive

alexandria:doplist (key val plist &optional values) forms*

Association List (alist)

acons key datum alist ⇒ new-alist

Append a cons and return a new alist. To modify an alist in place, use push.

(acons :c 3 '((:B . 2) (:A . 1))) ;⇒ ((:C . 3) (:B . 2) (:A . 1))
(push (cons :c 3) alist)          ;⇒ ((:C . 3) (:B . 2) (:A . 1))

pairlis keys data &optional alist ⇒ new-alist

Pair up elements in keys and data lists to make an alist.

(pairlis '(:a :b) '(1 2)) ;⇒ ((:B . 2) (:A . 1))

assoc item alist &key key test test-not ⇒ entry

Return the alist entry whose car satisfies the test, or nil. Functional variants are assoc-if and assoc-if-not. rassoc uses cdr to test.

(assoc :a '((:A . 1) (:B . 2)))         ;⇒ (:A . 1)
(rassoc 1 '((:A . 1) (:B . 2)))         ;⇒ (:A . 1)
(assoc-if #'evenp '((1 . :A) (2 . :B))) ;⇒ (2 . :B)

copy-alist alist ⇒ new-alist

Copies the cons cells that make up the alist structure.

alexandria:alist-plist alist

Converts an alist to a plist format.

(alist-plist '((:x . 10) (:y . 20))) ;⇒ (:x 10 :y 20)