この記事の要点
- Swift 4.2 が正式リリースされました。Swift 4 の強みを土台に、コンパイル時間の高速化、デバッグ体験の改善、標準ライブラリの更新を行い、さらに将来の binary compatibility(ABI 安定化)に向けて収束を進めたリリースです。Swift 4 / 4.1 / 3 とソース互換です。
- 言語面の目玉は、条件付き適合(conditional conformance)の完成(SE-0143)によるジェネリクスの前進と、
Hashableの刷新(SE-0206)・乱数生成 API の統一(SE-0202)といった標準ライブラリの更新です。 - ビルド面では batch mode コンパイルなどによりビルドが高速化し、コードサイズと実行時性能も改善しました。動的メンバールックアップ(SE-0195)や
#warning/#error(SE-0196)などの言語機能も加わりました。 - Apple プラットフォーム向けには Xcode 10 に同梱され、Linux(Ubuntu 14.04 / 16.04 / 18.04)向けの公式バイナリも提供されます。なお Swift 4.2 は Swift 3 とのソース互換を提供する最後のリリースです。
主な変更点
ジェネリクスの改善
条件付き適合(conditional conformance)のサポートが完成し(SE-0143)、Swift 4.2 は言語におけるジェネリクスの構想の実装を大きく前進させました。ジェネリクスのサポートが改善されると、コードに必要なボイラープレートが減り、より多くのコードを再利用できるようになります。
条件付き適合とは、ジェネリックな型が、その型引数が一定の条件を満たすときにだけプロトコルへ適合できる仕組みです。たとえば Array は、要素が Equatable のときにだけ Equatable に適合します。
標準ライブラリの更新
標準ライブラリには、Hashable プロトコルの改善や、新たに統一された乱数生成の関数・プロトコル群など、多くの新機能が加わりました。
-
Hashableの刷新(SE-0206): ハッシュ値の計算が、hashValueを自前で実装する方式から、Hasherに各構成要素を渡すhash(into:)方式へと変わりました。高品質なハッシュをより簡単に得られます。struct Point: Hashable { var x: Int var y: Int func hash(into hasher: inout Hasher) { hasher.combine(x) hasher.combine(y) } } -
乱数生成 API の統一(SE-0202): プラットフォームに依存しない乱数生成 API が標準ライブラリに導入されました。数値型や
Bool、コレクションに対して直接ランダムな値を得られます。let die = Int.random(in: 1...6) let flag = Bool.random() let shuffled = [1, 2, 3, 4, 5].shuffled() let picked = ["a", "b", "c"].randomElement() removeAll(where:)の追加(SE-0197): 条件に一致する要素を、その場で(in-place に)すべて削除します。Bool.toggle()の追加(SE-0199):Boolの値を反転します。flag = !flagをflag.toggle()と書けます。last(where:)/lastIndex(where:)の追加(SE-0204): 末尾側から条件に一致する最初の要素・インデックスを探します。Sequence.allSatisfy(_:)の追加(SE-0207): すべての要素が条件を満たすかどうかを判定します。
言語・コンパイラの更新
開発体験に目に見える影響を与える改善が多数入りました。
- batch mode コンパイルのサポートによるビルド時間の短縮
- retain / release 周りの呼び出し規約の変更によるコードサイズ削減と実行時性能の改善
-Ononeでの SIL デシリアライズの遅延化、再帰的なメタデータのサポート、よりコンパクトなリフレクションメタデータ- デフォルト引数の呼び出し側へのインライン化
initの宣言名や、1 ブロックに複数の case ラベルを持つswitch、ジェネリックなイニシャライザの継承など、長年の不具合の修正
また、Swift Evolution プロセスを経た次の Proposal も実装されています。
ImplicitlyUnwrappedOptional型の廃止(SE-0054)。再実装の詳細は implicitly unwrapped optional の再実装 も参照してください。- optional binding による
selfのweakから強参照への昇格(SE-0079) - モジュールをまたぐインライン化と特殊化(SE-0193)
-
enumのケースを集めた派生コレクション(CaseIterable)(SE-0194)enum Direction: CaseIterable { case north, south, east, west } for direction in Direction.allCases { print(direction) } - ユーザー定義の「動的メンバールックアップ」型(SE-0195)
-
コンパイラの診断ディレクティブ
#warning/#error(SE-0196)#warning("この実装は後で見直すこと") #if !canImport(Foundation) #error("このコードには Foundation が必要です") #endif - イミュータブルな値に対する
withUnsafePointer(to:_:)とwithUnsafeBytes(of:_:)(SE-0205) MemoryLayoutへのoffset(of:)メソッドの追加(SE-0210)- コンパイラバージョンのディレクティブ
#if swift(>=...)の拡張(SE-0212)
binary compatibility に向けた前進
Swift 4.2 は ABI の安定化へさらに近づき、将来のリリースでの binary compatibility を可能にする土台を整えました。ただし Swift 4.2 自体で ABI が安定するわけではありません。
Package Manager の更新
Swift Package Manager にも新機能が加わりました。
- batch mode のサポート: Swift ターゲットがコンパイラの batch mode でコンパイルされるようになりました。
- Xcode プロジェクトの自動生成:
generate-xcodeprojに--watchオプションが追加され、ファイルシステムを監視して必要に応じて Xcode プロジェクトを自動再生成します(watchman ツールを利用)。 - スキーム生成ロジックの改善: ルートパッケージの通常ターゲットとテストターゲットをすべて含むスキームと、実行可能ターゲットごとのスキームを生成します。
また、次の Package Manager 関連 Proposal も実装されています。
- ローカル依存のサポート(SE-0201)。git URL の代わりにディスク上のパスで依存を宣言できます(tools version 4.2 が必要)。
- システムライブラリターゲット(SE-0208)。従来パッケージ単位だったシステムモジュール機能をターゲット単位へ移しました。
- Swift 言語バージョン API の更新(SE-0209)。
swiftLanguageVersionsがIntの配列からSwiftVersionenum の配列へ変わりました。
移行とドキュメント
Swift 4.2 は Swift 4 / 4.1 / 3 とソース互換です。ただし、Swift 3 とのソース互換を提供する最後のリリースです。Xcode 10 には多くのソース変更を自動処理できるコードマイグレータが含まれ、機械的でない変更を案内する移行ガイドも用意されています。Swift 4.2 に対応した『The Swift Programming Language』の更新版も Swift.org で公開されています。
Swift 利用者への影響
- 既存コードへの影響は小さいです。 Swift 4.2 は Swift 4 / 4.1 / 3 とソース互換であり、多くのコードはそのままビルドできます。ただし Swift 3 とのソース互換はこのリリースが最後なので、まだ Swift 3 互換に依存している場合は移行を計画しておくとよいでしょう。
- ビルドが速く・軽くなります。 batch mode コンパイルでビルド時間が短縮され、呼び出し規約の変更やコンパクトなメタデータによりコードサイズと実行時性能も改善します。
- 標準ライブラリで書ける幅が広がります。 乱数生成 API の統一で
Int.random(in:)やshuffled()を標準で書けるようになり、removeAll(where:)・toggle()・allSatisfy(_:)・last(where:)などの便利なメソッドが加わりました。 Hashableの実装が楽になります。hash(into:)方式により、Hasherに構成要素を渡すだけで高品質なハッシュを得られます。CaseIterableや#warning/#errorが使えます。enumの全ケース列挙や、コンパイル時の警告・エラーの明示が手軽になりました。- 将来の ABI 安定化に向けた地ならしです。 Swift 4.2 自体では ABI は安定しませんが、後続リリースでの binary compatibility に必要な作業が進みました。
関連リンク
- このリリースの計画と管理方針については Swift 4.2 のリリースプロセス を参照してください。
swift-4.2-branchは、将来のバグ修正向け「ドット」リリースに備えて引き続き開かれた状態に保たれました。 - 前のマイナーリリースについては Swift 4.1 リリース を参照してください。
- 本記事に関連する解説記事: implicitly unwrapped optional の再実装
- 本記事で触れた主な Proposal ダイジェスト:
- Swift のダウンロード
- Swift Package Manager