Defining a new method for Arrays in all their forms

I've taken an interest in functional programming in Swift, so I was thinking about beefing up the support for that approach. For example, one could extend the Array map method to work on two lists quite easily:

extension Array {
    func map<I, O>(_ fn: (Element, I) -> O, _ secondList: [I]) -> [O] {
        zip(self, secondList).map {(a, b) in fn(a,b)}

The problem I've encountered is that as you perform various functional operations on Arrays, you don't just end up with Arrays--you end up with a lot of other data structures, such as ArraySlice, Array.Subsequence, Zip2Sequence, etc. These data structures provide some real value in that they eliminate the need to copy data around every time you, for example, take a slice of an array. However, this would seem to suggest that if I want to add a new method that will work consistently, even after other methods have been applied, then I need to add the method to every one of these datatypes. Unless either they conform to a common protocol that can be used, or I can write such a protocol.

Does anyone have suggestions on this? Is there a protocol that might be used for all list-like data structures, or would it be reasonable to write such a protocol? Or is the typical approach to write a method for every datatype? Thanks.

1 Like

There are a couple of protocols that abstract over these data structures:

zip specifically is generic over Sequence and defined as:

func zip<Sequence1, Sequence2>(
    _ sequence1: Sequence1,
    _ sequence2: Sequence2
) -> Zip2Sequence<Sequence1, Sequence2> where Sequence1 : Sequence, Sequence2 : Sequence

zip is a lazy algorithm and you can implement your own lazy/non-allocating algorithms. This is explained here: LazySequenceProtocol | Apple Developer Documentation

You might also be interested in the swift-algorithms package that has more lazy algorithms for sequences and collections: GitHub - apple/swift-algorithms: Commonly used sequence and collection algorithms for Swift


Thanks for the pointer. It looks like the right approach is to extend Sequence when possible, since that has broad coverage over so many collection types.

1 Like