• パラメータパックを使ったAPIの一般化

    Swiftのパラメータパックは、一般的なジェネリックパターンを簡素化することを可能にしながら、ジェネリックコードでできることを広げる強力なツールです。ジェネリックコードの型と引数の数を抽象化し、オーバーロードを避けるために一般的なジェネリックパターンをシンプルにする方法を紹介します。 このセッションを最大限に活用できるよう、WWDC22の 「Embrace Swift generics」をあらかじめ視聴されることをお勧めします。

    関連する章

    リソース

    関連ビデオ

    WWDC23

    WWDC22

  • ダウンロード
    Array
    • 1:13 - radians function

      func radians(from degrees: Double) -> Double
    • 1:26 - Array type

      struct Array<Element>
    • 1:48 - radians function and Array type with concrete expressions

      func radians(from degrees: Double) -> Double
      radians(from: 180)
      
      struct Array<Element>
      Array<Int>
    • 2:04 - generic query

      func query<Payload>(_ item: Request<Payload>) -> Payload
    • 2:22 - variadic query

      func query(_ item: Request...)
    • 3:16 - generic query

      func query<Payload>(_ item: Request<Payload>) -> Payload
    • 3:23 - two query overloads

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

      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)
    • 3:31 - four query overloads with extra argument error

      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)
    • 5:52 - for-in loop over requests

      for request in requests {
          evaluate(request)
      }
    • 8:41 - four query overloads

      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)
    • 9:37 - parameter pack query interface

      func query<each Payload>(_ item: repeat Request<each Payload>) -> (repeat each Payload)
    • 10:01 - parameter pack query with single argument call

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

      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>())
    • 10:15 - parameter pack query with triple argument call

      func query<each Payload>(_ item: repeat Request<each Payload>) -> (repeat each Payload)
      
      let results = query(Request<Int>(), Request<String>(), Request<Bool>())
    • 10:56 - parameter pack query interface

      func query<each Payload>(
          _ item: repeat Request<each Payload>
      ) -> (repeat each Payload)
    • 11:03 - parameter pack query interface with conformance

      func query<each Payload: Equatable>(
        _ item: repeat Request<each Payload>
      ) -> (repeat each Payload)
    • 11:17 - parameter pack query interface with where clause

      func query<each Payload>(
          _ item: repeat Request<each Payload>
      ) -> (repeat each Payload)
          where repeat each Payload: Equatable
    • 11:44 - parameter pack query interface with minimum parameter count

      func query<FirstPayload, each Payload>(
          _ first: Request<FirstPayload>, _ item: repeat Request<each Payload>
      ) -> (FirstPayload, repeat each Payload) 
          where FirstPayload: Equatable, repeat each Payload: Equatable
    • 13:42 - parameter pack query implementation

      struct Request<Payload> {
          func evaluate() -> Payload
      }
      
      func query<each Payload>(_ item: repeat Request<each Payload>) -> (repeat each Payload) {
          return (repeat (each item).evaluate())
      }
    • 16:04 - parameter pack query implementation with different input and output types

      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))
          }
      }
    • 17:05 - parameter pack query implementation with control flow break

      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
              }
          }
      }