Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2023 Developer ToolsSwift

WWDC23 · 18 min · Developer Tools / Swift

Generalize APIs with parameter packs

Swift parameter packs are a powerful tool to expand what is possible in your generic code while also enabling you to simplify common generic patterns. We’ll show you how to abstract over types as well as the number of arguments in generic code and simplify common generic patterns to avoid overloads. To get the most out of this session, we recommend first checking out “Embrace Swift generics" from WWDC22.

Watch at developer.apple.com ↗

Transcript all transcripts

Chapters

Code shown on screen · 22 snippets

radians function swift · at 1:13 ↗
func radians(from degrees: Double) -> Double
Array type swift · at 1:26 ↗
struct Array<Element>
radians function and Array type with concrete expressions swift · at 1:48 ↗
func radians(from degrees: Double) -> Double
radians(from: 180)

struct Array<Element>
Array<Int>
generic query swift · at 2:04 ↗
func query<Payload>(_ item: Request<Payload>) -> Payload
variadic query swift · at 2:22 ↗
func query(_ item: Request...)
generic query swift · at 3:16 ↗
func query<Payload>(_ item: Request<Payload>) -> Payload
two query overloads swift · at 3:23 ↗
func query<Payload>(
    _ item: Request<Payload>
) -> Payload

func query<Payload1, Payload2>(
    _ item1: Request<Payload1>,
    _ item2: Request<Payload2>
) -> (Payload1, Payload2)
three query overloads swift · at 3:28 ↗
func query<Payload>(
    _ item: Request<Payload>
) -> Payload

func query<Payload1, Payload2>(
    _ item1: Request<Payload1>,
    _ item2: Request<Payload2>
) -> (Payload1, Payload2)

func query<Payload1, Payload2, Payload3>(
    _ item1: Request<Payload1>,
    _ item2: Request<Payload2>,
    _ item3: Request<Payload3>
) -> (Payload1, Payload2, Payload3)
four query overloads with extra argument error swift · at 3:31 ↗
func query<Payload>(
    _ item: Request<Payload>
) -> Payload

func query<Payload1, Payload2>(
    _ item1: Request<Payload1>,
    _ item2: Request<Payload2>
) -> (Payload1, Payload2)

func query<Payload1, Payload2, Payload3>(
    _ item1: Request<Payload1>,
    _ item2: Request<Payload2>,
    _ item3: Request<Payload3>
) -> (Payload1, Payload2, Payload3)

func query<Payload1, Payload2, Payload3, Payload4>(
    _ item1: Request<Payload1>,
    _ item2: Request<Payload2>,
    _ item3: Request<Payload3>,
    _ item4: Request<Payload4>
) -> (Payload1, Payload2, Payload3, Payload4)

let _ = query(r1, r2, r3, r4, r5)
for-in loop over requests swift · at 5:52 ↗
for request in requests {
    evaluate(request)
}
four query overloads swift · at 8:41 ↗
func query<Payload>(
    _ item: Request<Payload>
) -> Payload

func query<Payload1, Payload2>(
    _ item1: Request<Payload1>,
    _ item2: Request<Payload2>
) -> (Payload1, Payload2)

func query<Payload1, Payload2, Payload3>(
    _ item1: Request<Payload1>,
    _ item2: Request<Payload2>,
    _ item3: Request<Payload3>
) -> (Payload1, Payload2, Payload3)

func query<Payload1, Payload2, Payload3, Payload4>(
    _ item1: Request<Payload1>,
    _ item2: Request<Payload2>,
    _ item3: Request<Payload3>,
    _ item4: Request<Payload4>
) -> (Payload1, Payload2, Payload3, Payload4)
parameter pack query interface swift · at 9:37 ↗
func query<each Payload>(_ item: repeat Request<each Payload>) -> (repeat each Payload)
parameter pack query with single argument call swift · at 10:01 ↗
func query<each Payload>(_ item: repeat Request<each Payload>) -> (repeat each Payload)

let result = query(Request<Int>())
parameter pack query with single and triple argument calls swift · at 10:08 ↗
func query<each Payload>(_ item: repeat Request<each Payload>) -> (repeat each Payload)

let result = query(Request<Int>())

let results = query(Request<Int>(), Request<String>(), Request<Bool>())
parameter pack query with triple argument call swift · at 10:15 ↗
func query<each Payload>(_ item: repeat Request<each Payload>) -> (repeat each Payload)

let results = query(Request<Int>(), Request<String>(), Request<Bool>())
parameter pack query interface swift · at 10:56 ↗
func query<each Payload>(
    _ item: repeat Request<each Payload>
) -> (repeat each Payload)
parameter pack query interface with conformance swift · at 11:03 ↗
func query<each Payload: Equatable>(
  _ item: repeat Request<each Payload>
) -> (repeat each Payload)
parameter pack query interface with where clause swift · at 11:17 ↗
func query<each Payload>(
    _ item: repeat Request<each Payload>
) -> (repeat each Payload)
    where repeat each Payload: Equatable
parameter pack query interface with minimum parameter count swift · at 11:44 ↗
func query<FirstPayload, each Payload>(
    _ first: Request<FirstPayload>, _ item: repeat Request<each Payload>
) -> (FirstPayload, repeat each Payload) 
    where FirstPayload: Equatable, repeat each Payload: Equatable
parameter pack query implementation swift · at 13:42 ↗
struct Request<Payload> {
    func evaluate() -> Payload
}

func query<each Payload>(_ item: repeat Request<each Payload>) -> (repeat each Payload) {
    return (repeat (each item).evaluate())
}
parameter pack query implementation with different input and output types swift · at 16:04 ↗
protocol RequestProtocol {
    associatedtype Input
    associatedtype Output
    func evaluate(_ input: Input) -> Output
}

struct Evaluator<each Request: RequestProtocol> {
    var item: (repeat each Request)

    func query(_ input: repeat (each Request).Input) -> (repeat (each Request).Output) {
        return (repeat (each item).evaluate(each input))
    }
}
parameter pack query implementation with control flow break swift · at 17:05 ↗
protocol RequestProtocol {
    associatedtype Input
    associatedtype Output
    func evaluate(_ input: Input) throws -> Output
}

struct Evaluator<each Request: RequestProtocol> {
    var item: (repeat each Request)

    func query(_ input: repeat (each Request).Input) -> (repeat (each Request).Output)? {
        do {
            return (repeat try (each item).evaluate(each input))
        } catch {
            return nil
        }
    }
}