Recursive constraints & higher-order generics
Write recursive constraints (e.g., nested sequences) and higher-order generic functions that take generic closures/functions.
What & why
This lesson shows:
- Recursive constraints: constraints on nested generic members (e.g., Sequence of Sequence).
- Higher-order generics: generic functions that accept generic closures/functions.
Nested sequences (flatten)
A classic recursive constraint: we require C.Element: Sequence so we can iterate two levels deep.
// Works for any Collection whose elements are Sequences
func flatten<C: Collection>(_ c: C) -> [C.Element.Element]
where C.Element: Sequence {
var result: [C.Element.Element] = []
result.reserveCapacity(c.reduce(0) { $0 + ($1 as AnySequence<C.Element.Element>).underestimatedCount })
for inner in c {
for e in inner { result.append(e) }
}
return result
}
let nested = [[1,2], [3], [4,5]]
print(flatten(nested)) // [1,2,3,4,5]All lessons in this course
- Conditional conformances
- Recursive constraints & higher-order generics
- where clauses on extensions