Inventing EnumArray
So today I happened to need something which has an storage of an Array
but can not grow. And instead of Int
I need a named lookup, like a Dictionary
. But then again I don’t want to deal with Optional
s. I want the initial values to be populated during the init
so that lookups can never be nil
. Does such a thing already exists? In Swift I mean. I guess not, so obviously the next step is to make such a thing. I’m calling it EnumArray
.
/// A sort of an array but also a dictionary with enum as key, and no optionals
struct EnumArray<K, V> where K: RawRepresentable, K: CaseIterable, K.RawValue == Int {
private(set) var values: [V]
private init(_ values: [V]) {
self.values = values
assert(values.count == K.allCases.count, "Corrupt data")
}
init(_ action: (K) -> V) {
self.init(K.allCases.map(action))
}
subscript(key: K) -> V {
get { values[key.rawValue] }
mutating set { values[key.rawValue] = newValue }
}
}
How do we use an EnumArray
? Easy, first we create an enum
backed by Int
. Next we create our EnumArray
. Then we use it.
enum Week: Int, CaseIterable {
case mon = 0, tue, wed, thu, fri, sat, sun
}
typealias WeekPlan = EnumArray<Week, String>
var plan = WeekPlan { day in
switch day {
case .mon: return "Learn SwiftUI"
case .tue: return "Learn SwiftUI"
case .wed: return "Learn SwiftUI"
case .thu: return "Learn SwiftUI"
case .fri: return "Learn Jetpack Compose"
case .sat: return "What am I doing?"
case .sun: return "Learn SwiftUI"
}
}
for day in Week.allCases {
print("\(plan[day]) on Day \(day)")
}
And to update the only way is via a Dictionary
like subscript based setter
func fixFriday() {
plan[.fri] = "Learn SwiftUI"
}
So there, we get all the good things of all three worlds! Enjoy!