name: swift-language-expert description: >- Use this skill for non-obvious Swift LANGUAGE and standard-library techniques -- features that make code clearer, safer, or faster but that developers routinely miss. Covers pattern matching (if/guard-case, switch over tuples); functions, closures, and key paths (variadics, autoclosures, rethrows); value semantics and custom types (copy-on-write, ~Copyable, callAsFunction, recursive enums, property wrappers); protocols and generics (associated types, opaque some vs existential any, phantom types); collections (lazy, RangeSet, InlineArray, sorting); strings and Unicode (grapheme-correct iteration, custom interpolation); concurrency and errors (async/await, task groups, AsyncStream, typed throws); and debugging and code organization (assertions, dump, enum namespaces, directives). Trigger for "how do I do X in Swift" and idiomatic refactors. Do NOT use for SwiftUI (swiftui-expert), app architecture or actor isolation in a layered app (ios-architecture-expert), or Swift Testing syntax (swift-testing-expert). metadata: version: 1.0.0 author: SwiftyJourney
Swift Language Expert
Non-obvious Swift language and standard-library techniques. This skill is about the language itself — not UI, not app architecture, not a test framework.
Agent Behavior Contract
When this skill is active, follow these rules strictly:
- Language & stdlib only. SwiftUI → defer to
swiftui-expert; app architecture / composition / where actor isolation goes in a layered app →ios-architecture-expert; Swift Testing (@Test/#expect) syntax →swift-testing-expert. - Prefer value types + copy-on-write for shared data; reach for a class only when you need identity, shared mutable state, or deinit/lifecycle.
- Prefer opaque
someover existentialanywhen a function returns one concrete type; useanyonly for genuinely heterogeneous storage, and know it costs dynamic dispatch + boxing. - Use
lazyfor chained collection transforms over large sequences to avoid intermediate allocations; eager is fine for small or single-pass work. - Respect Unicode. Iterate
Character(grapheme clusters) for user-perceived characters; never index aStringbyInt— useString.Index. - Prefer pattern matching (
if/guard case,switchwith tuples andwhere) over chainedif let/ boolean ladders. - Prefer structured concurrency (
async let,withTaskGroup) over detachedTask {}for child work. Where actor isolation belongs in an architecture is out of scope — defer toios-architecture-expert. - Gate recent language features by Swift/toolchain version:
~Copyable/borrowing/consuming, typedthrows,InlineArray, primary associated types,RangeSet.
Swift Technique Diagnostic Table
| Symptom / goal | Reach for | Deep dive |
|---|---|---|
Pyramid of nested if let / boolean ladders |
guard/if case, optional patterns, switch over tuples |
references/pattern-matching-and-control-flow.md |
An argument is evaluated even when unused (e.g. assert, log) |
@autoclosure (+ @escaping where needed) |
references/functions-closures-keypaths.md |
| Passing "which property" around as data | key-path expressions (\.name), key-path-as-function |
references/functions-closures-keypaths.md |
| A class used only to share/mutate a value | value type + copy-on-write (isKnownUniquelyReferenced) |
references/custom-types.md |
| A type that must never be copied (handle, lock, token) | ~Copyable + consuming/borrowing |
references/custom-types.md |
String-typed IDs of different kinds get mixed up |
phantom types (a generic tag parameter) | references/protocols-and-generics.md |
any Protocol everywhere / dynamic-dispatch cost |
some (opaque) vs any (existential); primary associated types |
references/protocols-and-generics.md |
filter + map over a huge collection allocates twice |
.lazy; RangeSet/DiscontiguousSlice for non-contiguous selection |
references/collections.md |
| Splitting/counting a string gives wrong results on emoji/accents | grapheme-cluster iteration, String.Index, normalization |
references/strings.md |
Hand-rolled pluralization / building strings with + |
custom StringInterpolation, raw strings |
references/strings.md |
| Fan out concurrent work and collect results | async let, withTaskGroup / withThrowingTaskGroup |
references/concurrency-and-errors.md |
| Bridge a delegate/callback API to async | AsyncStream, withCheckedContinuation |
references/concurrency-and-errors.md |
catch can't enumerate the errors a function throws |
typed throws |
references/concurrency-and-errors.md |
Global let constants polluting the namespace |
caseless enum namespace, type subscripts |
references/debugging-and-organization.md |
Guardrails
- Do not use a
classwhere astruct(+ copy-on-write if needed) suffices — reach for reference types only for identity/shared-mutable-state/lifecycle - Do not return
any Pwhen one concrete type is returned — usesome P - Do not index
Stringby integer offsets — useString.Index; iterateCharacterfor user-perceived characters - Do not chain
if letladders where aguard case/switchreads clearer - Do not spawn unstructured
Task {}for child work that should beasync let/ a task group - Do not solve SwiftUI, app architecture, or Swift Testing problems here — defer to the sibling skills
- Do not use bleeding-edge syntax without gating it by Swift/toolchain version
Reference Router
Open the smallest reference that matches the question:
- Control flow & functions
- pattern-matching-and-control-flow.md —
if/guard case,switchover tuples/ranges, optional patterns, labeled loops - functions-closures-keypaths.md — variadics, autoclosures,
rethrows, overloading, key paths
- pattern-matching-and-control-flow.md —
- Types
- custom-types.md — value semantics, copy-on-write,
~Copyable,callAsFunction,Comparable/literal conformances, recursive enums, property wrappers - protocols-and-generics.md — associated types,
Self,somevsany, primary associated types, phantom types, constraints
- custom-types.md — value semantics, copy-on-write,
- Data
- collections.md — lazy sequences,
RangeSet/DiscontiguousSlice,ContiguousArray/InlineArray, sorting,mapValues - strings.md —
String.Index, grapheme/Unicode handling, normalization, raw strings, custom interpolation
- collections.md — lazy sequences,
- Concurrency & errors
- concurrency-and-errors.md — async/await, structured concurrency,
AsyncSequence/AsyncStream, typedthrows
- concurrency-and-errors.md — async/await, structured concurrency,
- Tooling
- debugging-and-organization.md — assertions,
dump,CustomDebugStringConvertible, type subscripts, enum namespaces, compiler directives
- debugging-and-organization.md — assertions,