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