Skip to main content

nconc

nconc Function

Syntax:

nconc &rest lists → concatenated-list

Arguments and Values:

list—each but the last must be a list (which might be a dotted list but must not be a circular list); the last list may be any object.

concatenated-list—a list.

Description:

Returns a list that is the concatenation of lists. If no lists are supplied, (nconc) returns nil. nconc is defined using the following recursive relationship:

(nconc) → ()

(nconc nil . lists) (nconc . lists)

(nconc list) → list

(nconc list-1 list-2) (progn (rplacd (last list-1) list-2) list-1)

(nconc list-1 list-2 . lists) (nconc (nconc list-1 list-2) . lists)

Examples:

(nconc) → NIL 
(setq x ’(a b c))(A B C)
(setq y ’(d e f))(D E F)
(nconc x y)(A B C D E F)
x → (A B C D E F)
Note, in the example, that the value of x is now different, since its last *cons* has been **rplacd**’d to the value of y. If (nconc x y) were evaluated again, it would yield a piece of a *circular list*, whose printed representation would be (A B C D E F D E F D E F ...), repeating forever; if the **\*print-circle\*** switch were *non-nil*, it would be printed as (A B C . #1=(D E F . #1#)).
(setq foo (list ’a ’b ’c ’d ’e)
bar (list ’f ’g ’h ’i ’j)
baz (list ’k ’l ’m))(K L M)
(setq foo (nconc foo bar baz))(A B C D E F G H I J K L M)
foo → (A B C D E F G H I J K L M)
bar → (F G H I J K L M)
baz → (K L M)
(setq foo (list ’a ’b ’c ’d ’e)
bar (list ’f ’g ’h ’i ’j)
baz (list ’k ’l ’m))(K L M)
(setq foo (nconc nil foo bar nil baz))(A B C D E F G H I J K L M)
foo → (A B C D E F G H I J K L M)
bar → (F G H I J K L M)
baz → (K L M)

Side Effects:

The lists are modified rather than copied.

See Also:

append, concatenate

Expanded Reference: nconc

Destructive concatenation of lists

nconc concatenates lists by destructively modifying the cdr of the last cons of each list (except the last) to point to the next list.

(let ((x (list 1 2 3))
(y (list 4 5 6)))
(nconc x y))
=> (1 2 3 4 5 6)

nconc modifies the original lists

Unlike append, nconc does not copy. The original lists are modified in place.

(let ((x (list 'a 'b))
(y (list 'c 'd)))
(nconc x y)
x)
=> (A B C D)

Concatenating multiple lists

nconc can take any number of arguments.

(let ((a (list 1 2))
(b (list 3 4))
(c (list 5 6)))
(nconc a b c))
=> (1 2 3 4 5 6)

NIL arguments are skipped

NIL arguments are ignored, and the next non-nil list continues the chain.

(let ((x (list 'a 'b))
(y (list 'c 'd)))
(nconc nil x nil y nil))
=> (A B C D)

nconc with no arguments

Calling nconc with no arguments returns NIL.

(nconc)
=> NIL

Caution: do not nconc quoted lists

Because nconc is destructive, you should only use it on freshly consed lists (e.g., from list or copy-list), never on literal quoted lists.

;; SAFE: using list to create fresh conses
(let ((x (list 1 2))
(y (list 3 4)))
(nconc x y))
=> (1 2 3 4)

;; UNSAFE: (nconc '(1 2) '(3 4)) -- modifying literal data
;; is undefined behavior and should be avoided