5分で慣れるVariadic Generics

1.2K Views

January 23, 26

スライド概要

potatotips #94 iOS/Android開発Tips共有会の登壇資料です。
https://potatotips.connpass.com/event/376432/

profile-image

SwiftとLEGOとBluetooth LEが好きなプログラマ

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

ダウンロード

関連スライド

各ページのテキスト
1.

5分で慣れるVariadic Generics 大庭 慎一郎 @ooba / @bricklife

2.

話している人 大庭 慎一郎(おおば しんいちろう) ID: @ooba / @bricklife SwiftとLEGOが好きなプログラマ メルカリ1人目のiOSアプリエンジニア

3.

Variadic Generics 可変長ジェネリクス

5.
[beta]
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
}
}

出典: https://developer.apple.com/videos/play/wwdc2023/10168

6.
[beta]
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
}
}

出典: https://developer.apple.com/videos/play/wwdc2023/10168

7.

Not documented yet

8.

身近な例:SwiftUI

9.

// Xcode 14.3.1 / Swift 5.8.1 まで struct ContentView: View { var body: some View { VStack { Text("1") Text("2") Text("3") Text("4") Text("5") Text("6") Text("7") Text("8") Text("9") Text("10") Text("11") } } }

10.

// Xcode 15 / Swift 5.9 以降 struct ContentView: View { var body: some View { VStack { Text("1") Text("2") Text("3") Text("4") Text("5") Text("6") Text("7") Text("8") Text("9") Text("10") Text("11") } } }

11.
[beta]
@resultBuilder public struct ViewBuilder {
/// Builds an expression within the builder.
public static func buildExpression<Content>(_ content: Content) -> Content where Content : View
/// Builds an empty view from a block containing no statements.
public static func buildBlock() -> EmptyView
/// Passes a single view written as a child view through unmodified.
///
/// An example of a single view written as a child view is
/// `{ Text("Hello") }`.
public static func buildBlock<Content>(_ content: Content) -> Content where Content : View
public static func buildBlock<C0, C1>(_ c0: C0, _ c1: C1)
-> TupleView<(C0, C1)> where C0 : View, C1 : View
public static func buildBlock<C0, C1, C2>(_ c0: C0, _ c1: C1, _ c2: C2)
-> TupleView<(C0, C1, C2)> where C0 : View, C1 : View, C2 : View
public static func buildBlock<C0, C1, C2, C3>(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3)
-> TupleView<(C0, C1, C2, C3)> where C0 : View, C1 : View, C2 : View, C3 : View
・・・
public static func buildBlock<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>(_ c0: C0, _ c1: C1, _ c2:
C2, _ c3: C3, _ c4: C4, _ c5: C5, _ c6: C6, _ c7: C7, _ c8: C8, _ c9: C9)
-> TupleView<(C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)> where C0 : View, C1 : View, C2 :
View, C3 : View, C4 : View, C5 : View, C6 : View, C7 : View, C8 : View, C9 : View
}

12.
[beta]
@resultBuilder public struct ViewBuilder {
/// Builds an expression within the builder.
public static func buildExpression<Content>(_ content: Content) -> Content where Content : View
/// Builds an empty view from a block containing no statements.
public static func buildBlock() -> EmptyView
/// Passes a single view written as a child view through unmodified.
///
/// An example of a single view written as a child view is
/// `{ Text("Hello") }`.
public static func buildBlock<Content>(_ content: Content) -> Content where Content : View
public static func buildBlock<each Content>(_ content: repeat each Content)
-> TupleView<(repeat each Content)> where repeat each Content : View
}

13.

public static func buildBlock<C0, C1>(_ c0: C0, _ c1: C1) -> TupleView<(C0, C1)> where C0 : View, C1 : View public static func buildBlock<C0, C1, C2>(_ c0: C0, _ c1: C1, _ c2: C2) -> TupleView<(C0, C1, C2)> where C0 : View, C1 : View, C2 : View public static func buildBlock<C0, C1, C2, C3>(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3) -> TupleView<(C0, C1, C2, C3)> where C0 : View, C1 : View, C2 : View, C3 : View ・・・ public static func buildBlock<each Content>(_ content: repeat each Content) -> TupleView<(repeat each Content)> where repeat each Content : View

14.

public static func buildBlock<C0, C1>(_ c0: C0, _ c1: C1) -> TupleView<(C0, C1)> where C0 : View, C1 : View public static func buildBlock<C0, C1, C2>(_ c0: C0, _ c1: C1, _ c2: C2) -> TupleView<(C0, C1, C2)> where C0 : View, C1 : View, C2 : View public static func buildBlock<C0, C1, C2, C3>(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3) -> TupleView<(C0, C1, C2, C3)> where C0 : View, C1 : View, C2 : View, C3 : View ・・・ public static func buildBlock<each Content>(_ content: repeat each Content) -> TupleView<(repeat each Content)> where repeat each Content : View

15.
[beta]
public func create<Request: JSONRPCKit.Request>(_ request: Request) -> Batch1<Request> {
_ = semaphore.wait(timeout: DispatchTime.distantFuture)
let batchElement = BatchElement(request: request, version: version, id: idGenerator.next())
semaphore.signal()
}

return Batch1(batchElement: batchElement)

public func create<Request1: Request, Request2: Request>(_ request1: Request1, _ request2: Request2) -> Batch2<Request1, Request2> {
_ = semaphore.wait(timeout: DispatchTime.distantFuture)
let batchElement1 = BatchElement(request: request1, version: version, id: idGenerator.next())
let batchElement2 = BatchElement(request: request2, version: version, id: idGenerator.next())
semaphore.signal()
}

return Batch2(batchElement1: batchElement1, batchElement2: batchElement2)

public func create<Request1: Request, Request2: Request, Request3: Request>(_ request1: Request1, _ request2: Request2, _ request3: Request3) -> Batch3<Request1, Request2, Request3> {
_ = semaphore.wait(timeout: DispatchTime.distantFuture)
let batchElement1 = BatchElement(request: request1, version: version, id: idGenerator.next())
let batchElement2 = BatchElement(request: request2, version: version, id: idGenerator.next())
let batchElement3 = BatchElement(request: request3, version: version, id: idGenerator.next())
semaphore.signal()
}

return Batch3(batchElement1: batchElement1, batchElement2: batchElement2, batchElement3: batchElement3)

public func create<Request1: Request, Request2: Request, Request3: Request, Request4: Request>(_ request1: Request1, _ request2: Request2, _ request3: Request3, _ request4: Request4) ->
Batch4<Request1, Request2, Request3, Request4> {
_ = semaphore.wait(timeout: DispatchTime.distantFuture)
let batchElement1 = BatchElement(request: request1, version: version, id: idGenerator.next())
let batchElement2 = BatchElement(request: request2, version: version, id: idGenerator.next())
let batchElement3 = BatchElement(request: request3, version: version, id: idGenerator.next())
let batchElement4 = BatchElement(request: request4, version: version, id: idGenerator.next())
semaphore.signal()
}

return Batch4(batchElement1: batchElement1, batchElement2: batchElement2, batchElement3: batchElement3, batchElement4: batchElement4)

public func create<Request1: Request, Request2: Request, Request3: Request, Request4: Request, Request5: Request>(_ request1: Request1, _ request2: Request2, _ request3: Request3, _ request4:
Request4, _ request5: Request5) -> Batch5<Request1, Request2, Request3, Request4, Request5> {
_ = semaphore.wait(timeout: DispatchTime.distantFuture)
let batchElement1 = BatchElement(request: request1, version: version, id: idGenerator.next())
let batchElement2 = BatchElement(request: request2, version: version, id: idGenerator.next())
let batchElement3 = BatchElement(request: request3, version: version, id: idGenerator.next())
let batchElement4 = BatchElement(request: request4, version: version, id: idGenerator.next())
let batchElement5 = BatchElement(request: request5, version: version, id: idGenerator.next())
semaphore.signal()
}

return Batch5(batchElement1: batchElement1, batchElement2: batchElement2, batchElement3: batchElement3, batchElement4: batchElement4, batchElement5: batchElement5)

...

出典: https://github.com/bricklife/JSONRPCKit/blob/master/Sources/JSONRPCKit/BatchFactory.swift

16.

書き方

17.
[beta]
func same<each T>(_ item: repeat each T) -> (repeat each T) {
return (repeat each item)
}
same(1, "a", true)

// (1, "a", true)

18.
[beta]
func same<each T>(_ item: repeat each T) -> (repeat each T) {
return (repeat each item)
}
same(1, "a", true)

// (1, "a", true)

19.
[beta]
func same<each T>(_ item: repeat each T) -> (repeat each T) {
return (repeat each item)
}
same(1, "a", true)

// (1, "a", true)

20.
[beta]
func same<each T>(_ item: repeat each T) -> (repeat each T) {
return (repeat each item)
}
same(1, "a", true)

// (1, "a", true)

21.
[beta]
func same<each T>(_ item: repeat each T) -> (repeat each T) {
return (repeat each item)
}
same(1, "a", true)

// (1, "a", true)

func same<U, V, W>(_ u: U, _ v: V, _ v: W) -> (U, V, W) {
return (u, v, w)
}

22.
[beta]
func same<each T>(_ item: repeat each T) -> (repeat each T) {
return (repeat each item)
}
same(1, "a", true)

// (1, "a", true)

func same<U, V, W>(_ u: U, _ v: V, _ v: W) -> (U, V, W) {
return (u, v, w)
}

23.
[beta]
func optionalMap<each T>(_ item: repeat each T) -> (repeat Optional<each T>) {
return (repeat Optional(each item))
}
optionalMap(1, "a", true)

// (Optional(1), Optional("a"), Optional(true))

24.
[beta]
func optionalMap<each T>(_ item: repeat each T) -> (repeat Optional<each T>) {
return (repeat Optional(each item))
}
optionalMap(1, "a", true)

// (Optional(1), Optional("a"), Optional(true))

25.
[beta]
func optionalMap<each T>(_ item: repeat each T) -> (repeat Optional<each T>) {
return (repeat Optional(each item))
}
optionalMap(1, "a", true)

// (Optional(1), Optional("a"), Optional(true))

26.
[beta]
func optionalWrap<each T>(_ item: repeat each T) -> Optional<(repeat each T)> {
return Optional((repeat each item))
}
optionalWrap(1, "a", true)

// Optional((1, "a", true))

27.
[beta]
func resultMap<each T>(_ item: repeat each T) -> (repeat Result<each T, Never>) {
return (repeat Result<each T, Never>.success(each item))
}
resultMap(1, "a", true)

// (Result<Int, Never>.success(1),
// Result<String, Never>.success("a"),
// Result<Bool, Never>.success(true))

28.
[beta]
func extractResults<each T, each E: Error>(_ item: repeat Result<each T, each E>) throws
-> (repeat each T) {
return (repeat try (each item).get())
}
let r1 = Result<Int, any Error>.success(1)
let r2 = Result<String, any Error>.success("a")
let r3 = Result<Bool, any Error>.success(true)
try extractResults(r1, r2, r3)

// (1, "a", true)

29.
[beta]
func twice<each T>(_ item: repeat each T) -> (repeat each T, repeat each T) {
return (repeat each item, repeat each item)
}
twice(1, "a", true)

// (1, "a", true, 1, "a", true)

30.
[beta]
func pair<each T>(_ item: repeat each T) -> (repeat (each T, each T)) {
return (repeat (each item, each item))
}
pair(1, "a", true)

// ((1, 1), ("a", "a"), (true, true))

31.
[beta]
func append<each T, U>(_ t: (repeat each T), _ u: U) -> (repeat each T, U) {
return (repeat each t, u)
}
append((1, "a", true), 0.2)

// (1, "a", true, 0.2)

32.
[beta]
func double<each T: Numeric>(_ item: repeat each T) -> (repeat each T) {
return (repeat (each item) + (each item))
}
double(1, 0.2)

// (2, 0.4)

33.
[beta]
func double<each T: Numeric>(_ item: repeat each T) -> (repeat each T) {
return (repeat { $0 + $0 }(each item))
}
double(1, 0.2)

// (2, 0.4)

34.
[beta]
func double<each T: Numeric>(_ item: repeat each T) -> (repeat each T) {
return (
repeat { t in
t + t
}(each item)
)
}
double(1, 0.2)

// (2, 0.4)

35.
[beta]
func count<each T>(_ value: repeat each T) -> Int {
var count = 0
for _ in repeat each value {
count += 1
}
return count
}
count(1, "a", true)

// 3

36.
[beta]
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
}
}

出典: https://developer.apple.com/videos/play/wwdc2023/10168