Skip to main content

copy-tree

copy-tree Function

Syntax:

copy-tree tree → new-tree

Arguments and Values:

tree—a tree.

new-tree—a tree.

Description:

Creates a copy of a tree of conses.

If tree is not a cons, it is returned; otherwise, the result is a new cons of the results of calling copy-tree on the car and cdr of tree. In other words, all conses in the tree represented by tree are copied recursively, stopping only when non-conses are encountered.

copy-tree does not preserve circularities and the sharing of substructure.

Examples:

(setq object (list (cons 1 "one") 


(cons 2 (list ’a ’b ’c))))
((1 . "one") (2 A B C))
(setq object-too object)((1 . "one") (2 A B C))
(setq copy-as-list (copy-list object))
(setq copy-as-alist (copy-alist object))
(setq copy-as-tree (copy-tree object))
(eq object object-too) → true
(eq copy-as-tree object) → false
(eql copy-as-tree object) → false
(equal copy-as-tree object) → true
(setf (first (cdr (second object))) "a"
(car (second object)) "two"
(car object)(one . 1))(ONE . 1)
object → ((ONE . 1) ("two" "a" B C))
object-too → ((ONE . 1) ("two" "a" B C))
copy-as-list → ((1 . "one") ("two" "a" B C))
copy-as-alist → ((1 . "one") (2 "a" B C))
copy-as-tree → ((1 . "one") (2 A B C))

See Also:

tree-equal

Expanded Reference: copy-tree

Deep copy of a tree structure

copy-tree recursively copies all cons cells in a tree. Unlike copy-list, which only copies the top-level spine, copy-tree copies every level of nesting.

(let* ((original '((1 2) (3 (4 5))))
(copy (copy-tree original)))
(values copy
(equal original copy)
(eq original copy)))
=> ((1 2) (3 (4 5)))
=> T
=> NIL

Modifications to the deep copy do not affect the original

Because all cons cells are copied, even nested modifications are isolated.

(let* ((original (list (list 1 2) (list 3 4)))
(copy (copy-tree original)))
(setf (caar copy) 99)
(values original copy))
=> ((1 2) (3 4))
=> ((99 2) (3 4))

Contrast with copy-list

copy-list shares nested structure, while copy-tree does not.

(let* ((nested (list 'x 'y))
(original (list nested 'z))
(shallow (copy-list original))
(deep (copy-tree original)))
(values (eq (car original) (car shallow))
(eq (car original) (car deep))))
=> T
=> NIL

copy-tree with non-cons atoms

If the argument is not a cons, copy-tree returns it as-is (atoms are not copied).

(copy-tree 42)
=> 42

(copy-tree "hello")
=> "hello"

(copy-tree nil)
=> NIL

Practical use: safe tree manipulation

Use copy-tree when you need to modify a deeply nested structure without affecting the original.

(let ((template '(:html (:head (:title "Default"))
(:body (:p "Content")))))
(let ((page (copy-tree template)))
(setf (cadr (cadadr page)) "My Page")
(values template page)))
=> (:HTML (:HEAD (:TITLE "Default")) (:BODY (:P "Content")))
=> (:HTML (:HEAD (:TITLE "My Page")) (:BODY (:P "Content")))

copy-tree with dotted pairs

Dotted pairs within the tree are also recursively copied.

(let* ((original '((a . 1) (b . 2)))
(copy (copy-tree original)))
(setf (cdar copy) 99)
(values original copy))
=> ((A . 1) (B . 2))
=> ((A . 99) (B . 2))