LISP - Sequence Concatenation
Lisp - Sequence Concatenation
Section titled “Lisp - Sequence Concatenation”Common Lisp provides powerful, generic functions for operating on sequences. A sequence can be a list, a vector, or a string. The concatenate function is a versatile tool for combining multiple sequences into a new one.
Syntax
Section titled “Syntax”(concatenate result-type &rest sequences)Arguments
Section titled “Arguments”result-type: A type specifier symbol, such as'list,'vector,'string, indicating the type of the new sequence to be created.sequences: One or more sequences to be combined. They do not need to be of the same type.
Return Value
Section titled “Return Value”A new sequence of type result-type containing all elements from the input sequences in the given order.
Practical Examples
Section titled “Practical Examples”Combining Lists
Section titled “Combining Lists”The most common use case is combining two or more lists.
(let ((list1 '(1 2 3)) (list2 '(4 5 6))) (concatenate 'list list1 list2))Output
Section titled “Output”(1 2 3 4 5 6)Combining Mixed Sequence Types
Section titled “Combining Mixed Sequence Types”You can flexibly mix lists, vectors, and strings, and specify the desired output type.
;; Combine a list and a vector into a new vector(concatenate 'vector '(a b c) #(d e f))
;; Combine a list and a vector into a new list(concatenate 'list '(a b c) #(d e f))Output
Section titled “Output”#(A B C D E F)
(A B C D E F)Concatenating Strings
Section titled “Concatenating Strings”While concatenate works perfectly for strings, the format function is often considered more idiomatic and readable for this purpose.
;; Using concatenate(concatenate 'string "Hello, " "Lisp " "World!")
;; A more idiomatic way using format(format nil "Hello, ~a World!" "Lisp")Output (for both expressions)
Section titled “Output (for both expressions)”"Hello, Lisp World!"Performance Considerations and Alternatives
Section titled “Performance Considerations and Alternatives”concatenate is a great general-purpose tool, but it’s important to understand its performance characteristics. It always allocates a new sequence. If you are building up a large sequence by repeatedly adding elements in a loop, this can be inefficient.
Alternative for Building Lists
Section titled “Alternative for Building Lists”A common and highly efficient pattern for building a list is to push elements onto a temporary list and nreverse it at the end. push is very fast, and nreverse is a fast, in-place reversal.
(let ((result '())) (dolist (i '(1 2 3 4 5)) (push (* i i) result)) ; Pushes to the front (nreverse result)) ; Reverses the list to the correct orderOutput
Section titled “Output”(1 4 9 16 25)Alternative for Building Vectors
Section titled “Alternative for Building Vectors”For building vectors, create an adjustable vector with a fill pointer and use vector-push-extend.
(let ((vec (make-array 0 :adjustable t :fill-pointer 0))) (dotimes (i 5) (vector-push-extend (* i i) vec)) vec)Output
Section titled “Output”#(0 1 4 9 16)