🍊
Swift: クロージャの引数の意味を明確にしたい場合はタプルを使うと良い
Swiftでクロージャを使う際、呼び出し時に引数がどのように使われるかを明確にするために、引数にラベルをつけたいシーンがある。そういった場合は構造体やEnumを作成して対応していたが、タプルを使うことでよりシンプルに表現できる。
環境
- Swift 5.10
引数ラベルがないクロージャの例
let action: ((Int, Int) -> Void) = { x, y in
print(x, y)
}
action(1, 2)
上記のように、クロージャを呼び出す際に引数ラベルがないと、それぞれの引数がどのような意味を持つのか、どのように使われるのが分かりにくい。
以下のようには書けない。
// ❌ error: function types cannot have argument labels; use '_' before 'x'
let action: ((x: Int, y: Int) -> Void) = { x, y in
print(x, y)
}
action(x: 1, y: 2)
構造体を使って引数の意味を呼び出し側へ明示する
引数にラベルをつける一つの方法として、構造体を使うことが考えられる。以下のように構造体を定義し、その型を使うことで引数の意味を明確にできる。
struct Option {
let x: Int
let y: Int
}
let action: ((Option) -> Void) = { option in
print(option.x, option.y)
}
action(Option(x: 1, y: 2))
この方法でも機能するが、引数の個数が少ない場合、新たに構造体を定義するのはやや過剰なアプローチと感じる。そういった時は、タプルを使うとよりシンプルに解決できる。
タプルを使って引数の意味を呼び出し側へ明示する
タプルを使うと、構造体を使う時より少ないコード量で書ける。
let action: (((x: Int, y: Int)) -> Void) = { value in
print(value.x, value.y)
}
action((x: 1, y: 2))
この方法では、タプル内の各要素にラベルを付けることで、クロージャを呼び出す際に引数の意味が明確になる。
タプルも型の一つ[1]のため、構造体などと同様にクロージャのパラメータの型に使えるのは当然といえば当然だ。
Appendix: Swift 3.0より前では引数ラベルを書くことができた
Swift 3.0より前のバージョンでは引数ラベルを書くことができたが、現在はサポートされていない。
// Swift 3.0より前
let fn3 : (a: Int, b: Int) -> Bool
// Swift 3.0
let fn3 : (Int, Int) -> Bool
Discussion