The Missing Array.appending(contentsOf:)

The Swift standard library has a mutating func append(contentsOf:), but not an immutable variant.

Usually, the Array and Collection types offer both. I wonder why that’s not the case here. To be fair, the concatenation operator + does the same trick.

Here’s a basic implementation I’m using in my apps since forever, but which I haven’t shared, and which I never bothered to store in my code snippets repository (maybe because I believed that this would surely soon be added):

extension Array {
    public func appending(contentsOf other: Array<Element>) -> Array<Element> {
        var result = self
        result.append(contentsOf: other)
        return result
    }
}

But that’s not very elegant or generic.

Here’s how to find a better base type:

Searching for appending(contentsOf:) in the Swift documentation, a couple of results pop up: Array, ArraySlice, ContiguousArray, Data, RangeReplaceableCollection, Slice, String, Substring, and a couple others even further removed from an array.

So RangeReplaceableCollection is the most generic one I found that would do the trick. Sequence and Collection don’t offer append(contentsOf:), so these are all out.

Checking out append(contentsOf:) will reveal that the parameter can be any Sequence as long as it has the same Element type, which is nice for additional flexibility.

The result is this:

extension RangeReplaceableCollection {
    public func appending<Other>(contentsOf other: Other) -> Self
    where Other: Sequence, Other.Element == Element {
        var result = self
        result.append(contentsOf: other)
        return result
    }
}

That is a drop-in replacement for the Array extension from above, but unlike that, this will also work on Strings and Data etc. as well!

Like the concatenation operator +, this works on mixed left and right hand sides:

"abc".appending(contentsOf: ["d", "e", "f"])