この記事の要点
- Swift 4.1 が正式リリースされました。Swift 4.0 とソース互換のマイナーリリースで、ジェネリクスの拡充、新しいビルドオプション、Swift Package Manager や Foundation の小さな改善を含みます。Swift 5 で目指す ABI 安定化に向けた水面下の準備も大きく前進しました。
- 言語面の目玉は 条件付き適合(conditional conformance)(SE-0143)と、
Equatable/Hashableの自動合成(SE-0185)です。定型的な適合コードを大幅に減らせます。 - ビルド面では、コードサイズ最適化モード、モジュールの存在を調べる
canImport()(SE-0075)、シミュレータ判定のtargetEnvironment(simulator)(SE-0190)が加わりました。 - Apple プラットフォーム向けには Xcode 9.3 に同梱され、Linux(Ubuntu 14.04 / 16.04 / 16.10)向けの公式バイナリも提供されます。
主な変更点
言語の改善
Swift 4.1 は、Swift Generics Manifesto で掲げられた目標を一歩進める形で、ジェネリクス関連の機能を多数追加しています。
-
条件付き適合(SE-0143): ジェネリックな型が、その型引数が一定の条件を満たすときにだけプロトコルへ適合できるようになりました。たとえば
Arrayは、要素がEquatableのときにだけEquatableに適合します。標準ライブラリでの適用については 標準ライブラリにおける条件付き適合 も参照してください。extension Array: Equatable where Element: Equatable { static func == (lhs: [Element], rhs: [Element]) -> Bool { ... } } -
関連型への再帰的な制約のサポート(SE-0157): プロトコルの関連型に、自分自身を含むプロトコル自体を制約として課せるようになりました。
-
Equatable/Hashable適合の自動合成(SE-0185): すべての stored property がEquatable/Hashableなstructや、すべての関連値がEquatable/Hashableなenumでは、適合を宣言するだけで==やhashValueの実装が自動的に合成されます。手書きのボイラープレートが不要になります。struct Point: Equatable, Hashable { var x: Int var y: Int // == や hashValue は自動合成される } -
Sequence.compactMap(_:)の導入(SE-0187):nilを除外しながら変換する操作に、compactMap(_:)という分かりやすい名前が与えられました(従来のflatMap(_:)のうちnilを除外する用途を置き換えます)。let strings = ["1", "two", "3"] let numbers = strings.compactMap { Int($0) } // [1, 3] -
標準ライブラリの Index 型を
Hashableに(SE-0188): 標準ライブラリの各種インデックス型がHashableに適合し、DictionaryのキーやSetの要素として使えるようになりました。 -
CollectionからのIndexDistanceの削除(SE-0191):Collectionの関連型IndexDistanceが削除され、距離を表す型がIntに統一されました。ジェネリックなコードでインデックス間の距離を扱いやすくなります。
ビルドの改善
このリリースでは、ビルドを設定する手段がいくつか増えました。
- コードサイズ最適化モード: コンパイラが、コードサイズの削減に特化した新しい最適化モードをサポートするようになりました。詳細は Swift 4.1 のコードサイズ最適化モード を参照してください。
-
canImport()(SE-0075): あるモジュールをimportできるかどうかを、実際にimportせずに判定する条件付きコンパイル用の条件です。モジュールが存在すればtrue、なければfalseを返します。プラットフォームによって存在しないモジュールを扱うコードを書きやすくなります。#if canImport(UIKit) import UIKit #endif -
targetEnvironment(simulator)(SE-0190): シミュレータ向けにコンパイルされているときにtrueを返す条件です。シミュレータと実機で挙動を分けたい場合に使えます。#if targetEnvironment(simulator) // シミュレータ向けのコード #endif
Foundation
JSONEncoder と JSONDecoder に、エンコード・デコード時にキーを変換する新しいストラテジーが追加されました。たとえば、Swift 側の camelCase なプロパティ名と、JSON 側の snake_case なキー名を相互に変換できます。
そのほかの更新
このほか、Swift Evolution プロセスを経た次の Proposal も実装されています。
Unsafe[Mutable][Raw][Buffer]Pointerのメソッド追加・ラベル整理・確保サイズの扱いの変更(SE-0184)- プロトコルでの ownership キーワードのサポート削除(SE-0186)
- モジュールをまたぐ
structのイニシャライザの制限(SE-0189) - Playground QuickLook API の刷新(SE-0198)
ABI 安定化に向けた前進
Swift 4.1 には、Swift 5 での ABI 安定化に向けた水面下の変更が多数含まれます。参照カウント用のオブジェクトヘッダの調整、existential 型のメタデータレイアウトの決定、ジェネリック・プロトコル要件の正規化、ランタイム関数の監査、条件付き適合を使ったコレクションラッパーの統合などが完了しました。
Package Manager の更新
- 異なる URL スキーム(
sshとhttpなど)を使うパッケージグラフでも、依存を正しく解決できるようになりました。 - 共有依存を持つパッケージグラフで、依存解決の性能が大きく改善しました。
移行とドキュメント
Swift 4.1 は Swift 4.0 とソース互換です。それ以前のリリースからの移行を助けるため、Xcode 9.3 には多くのソース変更を自動処理できるコードマイグレータが含まれ、機械的でない変更を案内する移行ガイドも用意されています。Swift 4.1 に対応した『The Swift Programming Language』の更新版も Swift.org で公開されています。
Swift 利用者への影響
- 既存コードへの影響は小さいです。 Swift 4.1 は Swift 4.0 とソース互換であり、多くのコードはそのままビルドできます。一部の API ラベル変更などには対応が必要ですが、Xcode 9.3 のマイグレータが移行を支援します。
- ボイラープレートが減ります。
Equatable/Hashableの自動合成により、struct/enumの等価比較やハッシュ化のための手書きコードが不要になりました。compactMap(_:)でnil除外つきの変換も読みやすく書けます。 - ジェネリクスの表現力が増します。 条件付き適合により、「要素が
Equatableなら配列もEquatable」のような自然な適合を定義でき、ジェネリックなコードの設計の幅が広がります。 - プラットフォーム分岐が書きやすくなります。
canImport()とtargetEnvironment(simulator)により、モジュールの有無やシミュレータかどうかに応じたコードを安全に分岐できます。 - 将来の ABI 安定化に向けた地ならしです。 Swift 4.1 自体では ABI は安定しませんが、Swift 5 での安定化に必要な内部変更が着実に進みました。
関連リンク
- このリリースの計画と管理方針については Swift 4.1 のリリースプロセス を参照してください。
swift-4.1-branchは、将来のバグ修正向け「ドット」リリースに備えて引き続き開かれた状態に保たれました。次のリリースについては Swift 4.2 のリリースプロセス を参照してください。 - 前のメジャーリリースについては Swift 4.0 リリース を参照してください。
- 本記事に関連する解説記事: 標準ライブラリにおける条件付き適合 / Swift 4.1 のコードサイズ最適化モード
- 本記事で触れた主な Proposal ダイジェスト:
- Swift のダウンロード
- Swift Package Manager