💥

[Swift] parameter-packs を使って repeat で throws 関数を呼び出す時の注意点

2024/01/07に公開

タイトルがちょっとわかりづらいですが、 parameter-packs を使ってたらちょっとハマったのでメモ。

Swift5.9 から parameter-packs を使うことで以下のように書けるようになりました。

func foo<each T>(_ value: repeat each T) {
  repeat print(each value)
}

現在は制約が多いのでアプリケーション開発では使う場面が多くないのかなと思いつつ、ライブラリ開発では複数の値を受け取るときに [any Protocol] などとやる必要がなくパフォーマンス観点で便利だったりします。

そんな parameter-packs ですが、以下のように書くとコンパイラがクラッシュします。

func foo<each T>(_ value: repeat each T) {
  func inner<U>(_ value: U) throws {
    // 処理
  }
  
  try repeat inner(each value)
}

エラー内容もよくわからずハマりました。

色々試した結果、 try repeat ではなく repeat try と書くことでコンパイルが通るようになりました。

func foo<each T>(_ value: repeat each T) {
  func inner<U>(_ value: U) throws {
    // 処理
  }
  
  repeat try inner(each value) // ← try repeat から repeat try に変更
}

Swift は複数の throws な関数を呼び出すときに先頭に try をつけることでまとめることができるので癖で先頭に try をつけていたのですが、まさかこれでハマるとは・・・

// ↓ は
print(try inner(1), try inner(2))
// ↓ と書ける
try print(inner(1), inner(2))

環境

  • Xcode15.1
  • Apple Swift version 5.9.2 (swiftlang-5.9.2.2.56 clang-1500.1.0.2.5)

Discussion