Swift heterogeneous collections (mixed arrays, sets, dictionaries)

Mar 31, 2023#swift#faqs

Swift provides three primary collection types —arrays, sets, and dictionaries— implemented as generic types, which means they can store any type of value as long as it conforms to certain protocols.

Heterogeneous and homogeneous are terms that describe the types of values that a collection can store. A heterogeneous collection can store values of different types, as long as they conform to a common protocol. A homogeneous collection can only store values of the same type.

Swift does support heterogeneous collections, which are collections that can hold values of different types. However, there are some limitations and trade-offs to consider when using them.

  1. One way to create a heterogeneous collection is to use an existential type, such as any Animal, which can hold any type that conforms to the Animal protocol. For example:
let animals: [any Animal] = [Dog(name: "Spot"), Bird(name: "Tweety"), Fish(name: "Nemo")]

However, existential types have some drawbacks, such as being less efficient, less type-safe, and less expressive than generic type constraints.

  1. Another way to create a heterogeneous collection is to use a type-erasing wrapper, such as AnyHashable, which can hold any type that conforms to the Hashable protocol. For example:
let values: [AnyHashable] = [1, "hello", true]

However, type-erasing wrappers also have some drawbacks, such as losing some of the original type information and functionality, and requiring explicit casting to access the underlying value.

  1. A third way to create a heterogeneous collection is to use an enum with associated values, which can hold different types of values in each case. For example:
enum Value {
  case int(Int)
  case string(String)
  case bool(Bool)
}

let values: [Value] = [.int(1), .string("hello"), .bool(true)]

However, enums with associated values also have some drawbacks, such as being more verbose and requiring pattern matching to access the associated value.

Therefore, depending on your use case and requirements, you may choose one of these ways or a combination of them to create heterogeneous collections in Swift. Alternatively, you may consider using homogeneous collections with generic type constraints if possible, as they offer more advantages in terms of performance, type safety, and expressiveness.