要点
次の引数の数を変えたオーバーロードを
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)
次のようにまとめられる。
func query<each Payload>(_ item: repeat Request<each Payload>) -> (repeat each Payload)
次のように使用すると上記のeach Payload
にInt
, String
, Bool
が順繰りに入る。
let results = query(Request<Int>(), Request<String>(), Request<Bool>())
上記コードはWWDC2023の動画から拝借。
-
each Payload
は型引数パック (Type Parameter Pack)。英文法に照らしてeachの後は単数型が適切 -
item
は値引数パック (Value Parameter Pack) -
repeat
は繰返パターン(repetition pattern)。repeat each Payload
の表記は、一連の具象型をコンマで区切ったInt, String, Bool
のような表記に置き換わる。そのためTupleや関数宣言の括弧(...)
の中でのみ使用ができる
実験
下記コードをplaygroundにコピペすると挙動を確認できます。
(Swift5.9, Xcode 15.2で動作確認済)
// MARK: Protocol
protocol MockProtocol {
associatedtype Value
var value: Value { get }
var description: String { get }
}
extension MockProtocol {
var description: String { "\(value)" }
}
// MARK: Basic Structs
struct MockString: MockProtocol {
let value = "I am MockString"
}
struct MockInt: MockProtocol {
let value = 1
}
struct MockBool: MockProtocol {
let value = true
}
// MARK: Tuple Struct
struct MockTuple<each V: MockProtocol>: MockProtocol {
let value: (repeat each V)
init(_ value: repeat each V) {
self.value = (repeat each value)
}
}
extension MockTuple {
var description: String {
let descriptionTuple = (repeat (each value).description)
return "\(descriptionTuple)"
}
}
// Mark: Implementation
func returnMockTuple<each T: MockProtocol>(_ t: repeat each T) -> MockTuple<repeat each T> {
return MockTuple(repeat each t) // MockTupleB<Pack{MockString, MockInt, MockBool}>
}
returnMockTuple(MockString(), MockInt(), MockBool()).description // "("I am MockString", "1", "true")"
参考資料