---
title: 5分で慣れるVariadic Generics
tags: 
author: [Shinichiro Oba](https://convert.docswell.com/user/bricklife)
site: [Docswell](https://www.docswell.com/)
thumbnail: https://bcdn.docswell.com/page/9J215WLZ7R.jpg?width=480
description: potatotips #94 iOS/Android開発Tips共有会の登壇資料です。 https://potatotips.connpass.com/event/376432/
published: January 23, 26
canonical: https://convert.docswell.com/s/bricklife/K2QR31-variadic-generics-in-swift
---
# Page. 1

![Page Image](https://bcdn.docswell.com/page/9J215WLZ7R.jpg)

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


# Page. 2

![Page Image](https://bcdn.docswell.com/page/DEYZKLQN7M.jpg)

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


# Page. 3

![Page Image](https://bcdn.docswell.com/page/VJN3R4KVJ8.jpg)

Variadic Generics
可変長ジェネリクス


# Page. 4

![Page Image](https://bcdn.docswell.com/page/YE99MQVVE3.jpg)

Value and Type Parameter Packs
SE-0393
Implemented (Swift 5.9)


# Page. 5

![Page Image](https://bcdn.docswell.com/page/GE89LGP47D.jpg)

protocol RequestProtocol {
associatedtype Input
associatedtype Output
}
func evaluate(_ input: Input) throws -&gt; Output
struct Evaluator&lt;each Request: RequestProtocol&gt; {
var item: (repeat each Request)
}
func query(_ input: repeat (each Request).Input) -&gt; (repeat (each Request).Output)? {
do {
return (repeat try (each item).evaluate(each input))
} catch {
return nil
}
}
出典： https://developer.apple.com/videos/play/wwdc2023/10168


# Page. 6

![Page Image](https://bcdn.docswell.com/page/LELWLG1VJR.jpg)

protocol RequestProtocol {
associatedtype Input
associatedtype Output
}
func evaluate(_ input: Input) throws -&gt; Output
struct Evaluator&lt;each Request: RequestProtocol&gt; {
var item: (repeat each Request)
}
func query(_ input: repeat (each Request).Input) -&gt; (repeat (each Request).Output)? {
do {
return (repeat try (each item).evaluate(each input))
} catch {
return nil
}
}
出典： https://developer.apple.com/videos/play/wwdc2023/10168


# Page. 7

![Page Image](https://bcdn.docswell.com/page/4JM9MQWNEW.jpg)

Not documented yet


# Page. 8

![Page Image](https://bcdn.docswell.com/page/PJRGV8Y4E9.jpg)

身近な例：SwiftUI


# Page. 9

![Page Image](https://bcdn.docswell.com/page/PEXXZ8GZEX.jpg)

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


# Page. 10

![Page Image](https://bcdn.docswell.com/page/3EKW8K4VED.jpg)

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


# Page. 11

![Page Image](https://bcdn.docswell.com/page/L7312ZDQJ5.jpg)

@resultBuilder public struct ViewBuilder {
/// Builds an expression within the builder.
public static func buildExpression&lt;Content&gt;(_ content: Content) -&gt; Content where Content : View
/// Builds an empty view from a block containing no statements.
public static func buildBlock() -&gt; 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(&quot;Hello&quot;) }`.
public static func buildBlock&lt;Content&gt;(_ content: Content) -&gt; Content where Content : View
public static func buildBlock&lt;C0, C1&gt;(_ c0: C0, _ c1: C1)
-&gt; TupleView&lt;(C0, C1)&gt; where C0 : View, C1 : View
public static func buildBlock&lt;C0, C1, C2&gt;(_ c0: C0, _ c1: C1, _ c2: C2)
-&gt; TupleView&lt;(C0, C1, C2)&gt; where C0 : View, C1 : View, C2 : View
public static func buildBlock&lt;C0, C1, C2, C3&gt;(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3)
-&gt; TupleView&lt;(C0, C1, C2, C3)&gt; where C0 : View, C1 : View, C2 : View, C3 : View
・・・
public static func buildBlock&lt;C0, C1, C2, C3, C4, C5, C6, C7, C8, C9&gt;(_ c0: C0, _ c1: C1, _ c2:
C2, _ c3: C3, _ c4: C4, _ c5: C5, _ c6: C6, _ c7: C7, _ c8: C8, _ c9: C9)
-&gt; TupleView&lt;(C0, C1, C2, C3, C4, C5, C6, C7, C8, C9)&gt; where C0 : View, C1 : View, C2 :
View, C3 : View, C4 : View, C5 : View, C6 : View, C7 : View, C8 : View, C9 : View
}


# Page. 12

![Page Image](https://bcdn.docswell.com/page/87DXZRPWEG.jpg)

@resultBuilder public struct ViewBuilder {
/// Builds an expression within the builder.
public static func buildExpression&lt;Content&gt;(_ content: Content) -&gt; Content where Content : View
/// Builds an empty view from a block containing no statements.
public static func buildBlock() -&gt; 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(&quot;Hello&quot;) }`.
public static func buildBlock&lt;Content&gt;(_ content: Content) -&gt; Content where Content : View
public static func buildBlock&lt;each Content&gt;(_ content: repeat each Content)
-&gt; TupleView&lt;(repeat each Content)&gt; where repeat each Content : View
}


# Page. 13

![Page Image](https://bcdn.docswell.com/page/VJPPDWNXJ8.jpg)

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


# Page. 14

![Page Image](https://bcdn.docswell.com/page/2EV218K3EQ.jpg)

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


# Page. 15

![Page Image](https://bcdn.docswell.com/page/57GR25QYEL.jpg)

public func create&lt;Request: JSONRPCKit.Request&gt;(_ request: Request) -&gt; Batch1&lt;Request&gt; {
_ = semaphore.wait(timeout: DispatchTime.distantFuture)
let batchElement = BatchElement(request: request, version: version, id: idGenerator.next())
semaphore.signal()
}
return Batch1(batchElement: batchElement)
public func create&lt;Request1: Request, Request2: Request&gt;(_ request1: Request1, _ request2: Request2) -&gt; Batch2&lt;Request1, Request2&gt; {
_ = 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&lt;Request1: Request, Request2: Request, Request3: Request&gt;(_ request1: Request1, _ request2: Request2, _ request3: Request3) -&gt; Batch3&lt;Request1, Request2, Request3&gt; {
_ = 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&lt;Request1: Request, Request2: Request, Request3: Request, Request4: Request&gt;(_ request1: Request1, _ request2: Request2, _ request3: Request3, _ request4: Request4) -&gt;
Batch4&lt;Request1, Request2, Request3, Request4&gt; {
_ = 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&lt;Request1: Request, Request2: Request, Request3: Request, Request4: Request, Request5: Request&gt;(_ request1: Request1, _ request2: Request2, _ request3: Request3, _ request4:
Request4, _ request5: Request5) -&gt; Batch5&lt;Request1, Request2, Request3, Request4, Request5&gt; {
_ = 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


# Page. 16

![Page Image](https://bcdn.docswell.com/page/4EQVPZK6JP.jpg)

書き方


# Page. 17

![Page Image](https://bcdn.docswell.com/page/KJ4MY3PME1.jpg)

func same&lt;each T&gt;(_ item: repeat each T) -&gt; (repeat each T) {
return (repeat each item)
}
same(1, &quot;a&quot;, true)
// (1, &quot;a&quot;, true)


# Page. 18

![Page Image](https://bcdn.docswell.com/page/LE18619Y7G.jpg)

func same&lt;each T&gt;(_ item: repeat each T) -&gt; (repeat each T) {
return (repeat each item)
}
same(1, &quot;a&quot;, true)
// (1, &quot;a&quot;, true)


# Page. 19

![Page Image](https://bcdn.docswell.com/page/GEWZW8Q1E2.jpg)

func same&lt;each T&gt;(_ item: repeat each T) -&gt; (repeat each T) {
return (repeat each item)
}
same(1, &quot;a&quot;, true)
// (1, &quot;a&quot;, true)


# Page. 20

![Page Image](https://bcdn.docswell.com/page/47Z158WXJ3.jpg)

func same&lt;each T&gt;(_ item: repeat each T) -&gt; (repeat each T) {
return (repeat each item)
}
same(1, &quot;a&quot;, true)
// (1, &quot;a&quot;, true)


# Page. 21

![Page Image](https://bcdn.docswell.com/page/YJ6L9PGPEV.jpg)

func same&lt;each T&gt;(_ item: repeat each T) -&gt; (repeat each T) {
return (repeat each item)
}
same(1, &quot;a&quot;, true)
// (1, &quot;a&quot;, true)
func same&lt;U, V, W&gt;(_ u: U, _ v: V, _ v: W) -&gt; (U, V, W) {
return (u, v, w)
}


# Page. 22

![Page Image](https://bcdn.docswell.com/page/GJ51NKVP74.jpg)

func same&lt;each T&gt;(_ item: repeat each T) -&gt; (repeat each T) {
return (repeat each item)
}
same(1, &quot;a&quot;, true)
// (1, &quot;a&quot;, true)
func same&lt;U, V, W&gt;(_ u: U, _ v: V, _ v: W) -&gt; (U, V, W) {
return (u, v, w)
}


# Page. 23

![Page Image](https://bcdn.docswell.com/page/LE312ZD675.jpg)

func optionalMap&lt;each T&gt;(_ item: repeat each T) -&gt; (repeat Optional&lt;each T&gt;) {
return (repeat Optional(each item))
}
optionalMap(1, &quot;a&quot;, true)
// (Optional(1), Optional(&quot;a&quot;), Optional(true))


# Page. 24

![Page Image](https://bcdn.docswell.com/page/8EDXZRPMJG.jpg)

func optionalMap&lt;each T&gt;(_ item: repeat each T) -&gt; (repeat Optional&lt;each T&gt;) {
return (repeat Optional(each item))
}
optionalMap(1, &quot;a&quot;, true)
// (Optional(1), Optional(&quot;a&quot;), Optional(true))


# Page. 25

![Page Image](https://bcdn.docswell.com/page/V7PPDWNQ78.jpg)

func optionalMap&lt;each T&gt;(_ item: repeat each T) -&gt; (repeat Optional&lt;each T&gt;) {
return (repeat Optional(each item))
}
optionalMap(1, &quot;a&quot;, true)
// (Optional(1), Optional(&quot;a&quot;), Optional(true))


# Page. 26

![Page Image](https://bcdn.docswell.com/page/2JV218KPJQ.jpg)

func optionalWrap&lt;each T&gt;(_ item: repeat each T) -&gt; Optional&lt;(repeat each T)&gt; {
return Optional((repeat each item))
}
optionalWrap(1, &quot;a&quot;, true)
// Optional((1, &quot;a&quot;, true))


# Page. 27

![Page Image](https://bcdn.docswell.com/page/5EGR25QQJL.jpg)

func resultMap&lt;each T&gt;(_ item: repeat each T) -&gt; (repeat Result&lt;each T, Never&gt;) {
return (repeat Result&lt;each T, Never&gt;.success(each item))
}
resultMap(1, &quot;a&quot;, true)
// (Result&lt;Int, Never&gt;.success(1),
// Result&lt;String, Never&gt;.success(&quot;a&quot;),
// Result&lt;Bool, Never&gt;.success(true))


# Page. 28

![Page Image](https://bcdn.docswell.com/page/4JQVPZKW7P.jpg)

func extractResults&lt;each T, each E: Error&gt;(_ item: repeat Result&lt;each T, each E&gt;) throws
-&gt; (repeat each T) {
return (repeat try (each item).get())
}
let r1 = Result&lt;Int, any Error&gt;.success(1)
let r2 = Result&lt;String, any Error&gt;.success(&quot;a&quot;)
let r3 = Result&lt;Bool, any Error&gt;.success(true)
try extractResults(r1, r2, r3)
// (1, &quot;a&quot;, true)


# Page. 29

![Page Image](https://bcdn.docswell.com/page/K74MY3P1J1.jpg)

func twice&lt;each T&gt;(_ item: repeat each T) -&gt; (repeat each T, repeat each T) {
return (repeat each item, repeat each item)
}
twice(1, &quot;a&quot;, true)
// (1, &quot;a&quot;, true, 1, &quot;a&quot;, true)


# Page. 30

![Page Image](https://bcdn.docswell.com/page/LJ186195EG.jpg)

func pair&lt;each T&gt;(_ item: repeat each T) -&gt; (repeat (each T, each T)) {
return (repeat (each item, each item))
}
pair(1, &quot;a&quot;, true)
// ((1, 1), (&quot;a&quot;, &quot;a&quot;), (true, true))


# Page. 31

![Page Image](https://bcdn.docswell.com/page/GJWZW8QWJ2.jpg)

func append&lt;each T, U&gt;(_ t: (repeat each T), _ u: U) -&gt; (repeat each T, U) {
return (repeat each t, u)
}
append((1, &quot;a&quot;, true), 0.2)
// (1, &quot;a&quot;, true, 0.2)


# Page. 32

![Page Image](https://bcdn.docswell.com/page/4EZ158W273.jpg)

func double&lt;each T: Numeric&gt;(_ item: repeat each T) -&gt; (repeat each T) {
return (repeat (each item) + (each item))
}
double(1, 0.2)
// (2, 0.4)


# Page. 33

![Page Image](https://bcdn.docswell.com/page/Y76L9PX6JV.jpg)

func double&lt;each T: Numeric&gt;(_ item: repeat each T) -&gt; (repeat each T) {
return (repeat { $0 + $0 }(each item))
}
double(1, 0.2)
// (2, 0.4)


# Page. 34

![Page Image](https://bcdn.docswell.com/page/G751NKX5E4.jpg)

func double&lt;each T: Numeric&gt;(_ item: repeat each T) -&gt; (repeat each T) {
return (
repeat { t in
t + t
}(each item)
)
}
double(1, 0.2)
// (2, 0.4)


# Page. 35

![Page Image](https://bcdn.docswell.com/page/9J215WXG7R.jpg)

func count&lt;each T&gt;(_ value: repeat each T) -&gt; Int {
var count = 0
for _ in repeat each value {
count += 1
}
return count
}
count(1, &quot;a&quot;, true)
// 3


# Page. 36

![Page Image](https://bcdn.docswell.com/page/DEYZKL8G7M.jpg)

protocol RequestProtocol {
associatedtype Input
associatedtype Output
}
func evaluate(_ input: Input) throws -&gt; Output
struct Evaluator&lt;each Request: RequestProtocol&gt; {
var item: (repeat each Request)
}
func query(_ input: repeat (each Request).Input) -&gt; (repeat (each Request).Output)? {
do {
return (repeat try (each item).evaluate(each input))
} catch {
return nil
}
}
出典： https://developer.apple.com/videos/play/wwdc2023/10168


# Page. 37

![Page Image](https://bcdn.docswell.com/page/VJN3R4Q8J8.jpg)



