/*:#localized(key: "WrappingUp")
 # Wrapping up

 A task group is what you reach for when the number of parallel jobs is decided at
 runtime rather than fixed in the source: fan the work out, then collect results
 as they finish, with the structured scope guaranteeing nothing leaks. The catch
 that trips most people is result *ordering*, so keep the takeaways below in mind
 before you trust it.

 * Use a **task group** when the number of parallel jobs is *dynamic*; use
 `async let` when it's a small *fixed* set.
 * `withTaskGroup(of:)` opens the group, `group.addTask { }` spawns a child per
 item, and `for await result in group` collects results as they finish.
 * Results arrive in **completion order**, not submission order: return
 `(index, value)` from each child and sort at the end if you need the original
 order; never index into results by arrival position.
 * **Consume the group by iterating it.** If you `addTask` but never `for await`
 over it, the group still waits for every child at the end of scope; you've just
 thrown the results away. (For deliberate fire-and-forget children, use
 `withDiscardingTaskGroup` so you're saying so on purpose.)
 * `withThrowingTaskGroup` rethrows the first child error and cancels the rest;
 catch it around the group. To skip failures instead, return an optional from a
 plain group.
 * The **structured guarantee**: the group scope never returns while a child is
 still running, so nothing leaks; cancellation flows down to every child.
 * For large `N`, **cap the in-flight count** (prime with `N` tasks, then add one
 as each finishes) to bound memory and load.

 ---
 
 ## Up next

 The next chapter is [Actors](Actors.playgroundchapter/Overview). You've been carefully avoiding shared mutable state
 across these parallel tasks; now meet the type that makes sharing it *safe*.

 [Previous](@previous)  |  page 9 of 9
 */
