Skip to main content

copy-alist

copy-alist Function

Syntax:

copy-alist alist → new-alist

Arguments and Values:

alist—an association list.

new-alist—an association list.

Description:

copy-alist returns a copy of alist.

The list structure of alist is copied, and the elements of alist which are conses are also copied (as conses only). Any other objects which are referred to, whether directly or indirectly, by the alist continue to be shared.

Examples:

(defparameter \*alist\* (acons 1 "one" (acons 2 "two"()))) 

\*alist\* → ((1 . "one") (2 . "two"))
(defparameter \*list-copy\* (copy-list \*alist\*))
\*list-copy\* → ((1 . "one") (2 . "two"))
(defparameter \*alist-copy\* (copy-alist \*alist\*))
\*alist-copy\* → ((1 . "one") (2 . "two"))
(setf (cdr (assoc 2 \*alist-copy\*)) "deux")"deux"
\*alist-copy\* → ((1 . "one") (2 . "deux"))
\*alist\* → ((1 . "one") (2 . "two"))
(setf (cdr (assoc 1 \*list-copy\*)) "uno")"uno"
\*list-copy\* → ((1 . "uno") (2 . "two"))
\*alist\* → ((1 . "uno") (2 . "two"))

See Also:

copy-list

Expanded Reference: copy-alist

Basic usage

copy-alist creates a copy of an association list, making fresh copies of both the top-level spine and each cons pair (the key-value pairs).

(let ((original '((a . 1) (b . 2) (c . 3))))
(copy-alist original))
=> ((A . 1) (B . 2) (C . 3))

Modifying the copy does not affect the original

Because copy-alist copies each cons pair, modifying a value in the copy does not change the original alist.

(let* ((original '((a . 1) (b . 2)))
(copied (copy-alist original)))
(setf (cdr (assoc 'a copied)) 99)
(values original copied))
=> ((A . 1) (B . 2))
=> ((A . 99) (B . 2))

Difference from copy-list

copy-list only copies the spine (top-level conses) but shares the cons pairs. Modifying a pair through a copy-list result also modifies the original.

(let* ((original (list (cons 'x 10) (cons 'y 20)))
(list-copy (copy-list original))
(alist-copy (copy-alist original)))
;; Modifying through list-copy affects original
(setf (cdr (assoc 'x list-copy)) 999)
;; Modifying through alist-copy does NOT affect original
(setf (cdr (assoc 'y alist-copy)) 888)
(values original list-copy alist-copy))
=> ((X . 999) (Y . 20))
=> ((X . 999) (Y . 20))
=> ((X . 10) (Y . 888))

Shared values are still shared

While the cons pairs are copied, the actual key and value objects are still shared (not deeply copied).

(let* ((shared-value (list 1 2 3))
(original (list (cons 'data shared-value)))
(copied (copy-alist original)))
(eq (cdr (first original))
(cdr (first copied))))
=> T