Swift 3.0 をいまから学ぶ Swift Evolution ウォッチング

おはようございます。シニアアプリケーションエンジニアの id:cockscomb です。WWDC が目前に迫ったいま、今秋にリリースが予定されている Swift 3.0 について、Swift OSS コミュニティの中心である Swift Evolution から読み取っていきたいと思います。


[PR]

本記事は、筆者が株式会社はてなの協賛を得て主催した「関西モバイルアプリ研究会 #14」において、“Swift Otaku — Nerdy Swift-Evolution Watching” と題して発表したものをブログの記事として再構成したものである。

関西モバイルアプリ研究会は、毎月一度、平日夜に京都や大阪で開催される、モバイルアプリ関連の勉強会である。次回の「関西モバイルアプリ研究会 #15」は6月22日水曜日に開催予定だ。

f:id:cockscomb:20160609234540p:plain


目次


Swift 3.0 はこの秋にリリースが予定されている。Swift 3 Release Process から考えると、1週間後の Apple World Wide Developers Conference (WWDC) 2016 に合わせて最初の Developer Preview バージョンがリリースされるはずだ。オープンソース化されたとはいえ、基本的には Apple のスケジュールに左右される。Swift 3.0 はいったいどのようなアップデートになるのだろうか。

OSS になった Swift は、swift-evolution メーリングリスト での議論や、GitHub の Swift Evolution にまとめられた proposal によって、将来の変更を決定している。これらを追うことで、Swift 3.0 やその先のリリースについて知ることができる。

Focus

Swift Evolution によれば Swift 3.0 は以下のことに焦点を当てるとされる。

  • API design guidelines
  • Automatic application of naming guidelines to imported Objective-C APIs
  • Adoption of naming guidelines in key APIs
  • Swiftification of imported Objective-C APIs
  • Focus and refine the language
  • Improvements to tooling quality

このほか portability もまた重要であることが明言されている。Swift Evolution で議論される proposal は、基本的にはこれらのトピックに関連しているはずだ。

ところで、当初 Swift 3.0 での目標とされていたいくつかのトピックが削除されていることに気付くだろうか。

Winding Down

5月半ばに Chris Lattner は、“Winding down the Swift 3 release” と題したメールをコミュニティに送った。そこには ABI の安定化と、そのために必要な generics の機能を完成を、Swift 3.0 のリリースから見送ることが書かれている。また Swift 3.0 では API naming という困難に向き合い、ソースコードレベルでの安定化が図られたということが強調されている。つまり将来のバージョンの Swift でも、可能な限りソースコードの互換性が維持されることが期待されている。そして、Swift 3.0 以降の 3.x や 4.0 については、今年の8月以降に議論を再開するとされた。

コミュニティからは ABI の安定化が見送られることについてネガティブな反応が見られたが、Chris Lattner を含む Swift Core Team は丁寧にそれに答えている。Objective-C の時代に起きた ABI に関する問題の例を挙げて、スケジュール上の圧力が ABI に問題を引き起こすのを避けるためには急ぐべきではないことを説明している。

ところで今回は見送られた generics の完成や ABI の安定化とは何だろうか。本論からは少し脱線するが、簡単に覗いてみよう。

Complete Generics

標準ライブラリの ABI を安定させるためには、標準ライブラリで本来は利用したいと考えられる generics の機能を実装する必要がある。“Generics Manifesto” と題されたドキュメントは、元は Swift Evolution のメーリングリストに投稿されたものであるが、そういった generics の展望を示したものである。Generics が拡張されることで、Swift の表現力もさらに改善される。

ABI Stability

Swift における Application Binary Interface (ABI) の安定とはつまり、異なるバージョンの Swift コンパイラでコンパイルしたバイナリがリンクできる状態である。このために Swift は、言語機能の重要な部分を確定させると共に、実行時のデータ構造や呼び出しの規約などを仕上げなければならない。標準ライブラリについてもそのインターフェースを確定させる必要がある。

ABI の安定化と共に、Resilience と呼ばれる機能も必要とされている。Resilience (弾力)Fragile (壊れやすい) に対応する語として使われている。Swift で書かれたライブラリが ABI 上の互換性を保つための機能である。

例えばライブラリの公開インターフェースとなっている struct に、新たに stored property を追加したらどうなるだろう。あるいは enum に後から case を追加できるとしたら、網羅性の検査に影響があるのではないか。

今のところの計画では、ライブラリはその API をバージョニングできるようになる。また stored property の追加やその定義順の変化は ABI を壊すことなく実現可能である。enum についても通常は case の追加を許容するが、case の追加が起きない @closed な enum を作ることもできる。一般に、後から変えても ABI 上の互換性を保つことは実行時のパフォーマンスに影響するが、必要な場合にこれを解消できるように、@inlinable な関数や @fixed_contents な struct を作ることもできる。

このような内容は “Library Evolution” と題されたドキュメントにまとめられている。ただしこれらは Swift Evolution での議論を経ておらず、実現する際にはいくらか違ったものになっているかもしれない。

Proposals

本題に戻って、Swift 3.0 に関して Swift Evolution でこれまでに議論されてきた proposal の中から、いくつか興味を惹かれるものを見ていこう。

Naming Guidelines

Swift の新しいネーミングガイドラインに関する proposal は多い。その中でも上記の3つが基本的なものである。新しいガイドラインは “API Design Guidelines” としてまとめられており、それを標準ライブラリや Objective-C からのインポートにも適用するところまでがこれらである。

関連する proposal は他にもある。

この中でも SE-0044 Import as member は、例えば Core Graphics などのフレームワークに見られる CGContextSetLineWidth(_:_:) のような、第一引数に(オブジェクト指向のイメージではメソッドのレシーバに相当する)struct への参照をとる(この場合は CGContextRef)関数を、context.lineWidth = width のようなフォームへ変えられる。Objective-C だけでなく、C の API まで Swift らしくすることができ、画期的である。

Core Libraries

Swift 3.0 では、Apple 以外のプラットフォーム向けにも Core Libraries として Foundation/Grand Central Dispatch/XCTest の3つが提供される。これに伴う proposal もいくつか存在している。

実は SE-0005 Better Translation of Objective-C APIs Into Swift の proposal には当初、Foundation から NS prefix を取り除くことが盛り込まれていた。しかし rationale にあるように、参照型のセマンティクスを持つ Foundation と値型のセマンティクスを持つ標準ライブラリの矛盾といったことを含むいくつかの理由からいったん見送られていた。

SE-0069 Mutability and Foundation Value Types では Foundation のいくつかの class について対応する struct を導入する。例えば NSDateDate のように、NS prefix の取り除かれた struct の導入で値型のセマンティクスを得る。

SE-0086 Drop NS Prefix in Swift Foundation は、ついに NS prefix を取り除こうという proposal である。基本的な方針は、Objective-C ランタイムと関連していたり、Apple のプラットフォームと関連していたりするものは NS prefix を残し、あとは prefix を削除するというものである。現在まだレビュー中であるが、多少議論が分かれている。

Grand Central Dispatch (GCD) の API を Swift らしくしようというのがこの proposal である。GCD はもともと C で API を提供しているが、例えば dispatch_queue_t 型を DispatchQueue 型にしたり、グローバル関数をメソッドにしたりすることで、より Swift らしいインターフェースに変えるというものだ。

Objective-C

Objective-C で書かれたコードとのインタラクションも Swift 3.0 ではさらに改善される。可能な限りコンパイル時に検証しようとするのは良いことである。

ところで、Objective-C の class でも property が利用できるようになる予定である。Swift のバグトラッカーに登録された Unknown property attribute 'class' を見ると(すでに修正されたが)、そのことがわかる。Apple Clang コンパイラは将来のバージョンで Objective-C class properties をサポートする予定だ。このように、Objective-C もまた Swift に合わせて進化しようとしている。

Swift Package Manager

Swift のエコシステムを強化するため Swift 3.0 から新たにツールチェーンに加わる Swift Package Manager (SwiftPM) もまた、活発に議論されている分野である。リリース前であるにも関わらず、専ら実用性を意識した proposal が多いようにみられるが、これはコミュニティの期待感のあらわれではないだろうか。

クローズドソースの Xcode が今年の WWDC 以降にどれくらい SwiftPM と連携していくのか、そういった期待もある。

Swift Language

純粋なプログラミング言語としての Swift にも、様々な変化が待っている。

可視性のスコープ

シンボルの可視性が整理される。Swift 2.2 までの private は、それが書かれたソースファイルの中からだけ参照できるというものだった。Swift の extension 機能には便利な場面がある一方で、他の言語とは一貫しない仕様である。Swift 3.0 からは、このような可視範囲を fileprivate として、新たにその定義中でのみ可視の private を加えた。これによって Swift の可視性のスコープは以下の4つになる。

キーワード 可視性
public モジュールの外部まで可視
internal モジュールの内部だけに可視
fileprivate そのファイルの中だけに可視
private 現在の定義の中だけに可視

関数

関数については、初期の Swift で柔軟だった点を、より厳密にするような方向性の変化が多い。特にコンパイラの実装を複雑にする割にそれほど活用されていないと考えられる仕様が取り除かれている。

ImplicitlyUnwrappedOptional

ImplicitlyUnwrappedOptional という型を Swift から無くし、! のついた型を @_autounwrapped 属性のついた Optional 派生型として取り扱おうという proposal。暗黙的に wrap される Optional 型は、特に型システムが比較的弱い Objective-C との連携のために必要ではあるが、そのような理由がなければ代替手段によって取って代わられるべきものである。このため必要のない場面では使われないように、制限を設けようというものである。

dynamicType

SE-0068 Expanding Swift Self to class members and value types では、インスタンスにおいて Selfself.dynamicType の意味で利用できるようになる。このことでインスタンスから型の持つメンバーへのアクセスが簡単になり、構文における意味も明瞭になる。

さらに SE-0096 Converting dynamicType from a property to an operator では、インスタンスからその型を得る .dynamicType property を dynamicType() 演算子に変える。これは dynamicType の働きが property というよりは sizeof などの演算子に近いのではないかという動機によるものである。

暗黙的な変換

SE-0072 Fully eliminate implicit bridging conversions from Swift では、Swift 標準ライブラリの型と Foundation の型の暗黙的な変換 (String から NSString のような) を一切やめて、必ず as でキャストすることになる。Swift 1.2 のときに Foundation から標準ライブラリの型への変換が無くなったが、Objective-C の lightweight generics 機能などによって多くの変換が不要になった現在では、暗黙的な変換をすべてやめたとしてもその影響は限定的であるとされた。

SE-0083 Remove bridging conversion behavior from dynamic casts はさらに、as によるキャストで変換するのもやめ、イニシャライザを利用しようという proposal である。コミュニティからのフィードバックもポジティブである。ところが前述のSE-0072 について、Objective-C の id 型に関連して極端な問題が起きるという懸念が発生しており、これについて明確になるまでは議論が延期されている。

コンパイラ制御文

#if canImport(ModuleName) というコンパイラ制御文によって、モジュールがインポート可能かどうかのテストを行えるようになる。

Generics

  • SE-0048 Generic Type Aliases (Accepted)
    • 型パラメータを持った typealias を定義できる。ただしあくまでも typealias であって、新たな型が作られるわけではない
  • SE-0081 Move where clause to end of declaration (Accepted)
    • 型パラメータに関連する where 節を、型パラメータの括弧 (<>) の中ではなく、定義本体の直前にする
  • SE-0092 Typealiases in protocols and protocol extensions (Accepted)
    • Swift 2.2 から protocol の associated type が typealias ではなく専用の associatedtype キーワードで表すことになったので、空いた typealias キーワードで protocol 中での typealias に利用できるようにする
  • SE-0095 Replace protocol<P1,P2> syntax with P1 & P2 syntax (TBD)
    • 複数の protocol に準拠している型を表す protocol<P1, P2> 構文を P1 & P2 という構文に変える。当初は Any<P1, P2> 構文が提案されていたが、P1 AND P2 ではなく P1 OR P2 と誤解する恐れがあるというコミュニティのフィードバックを受けて、論理積を表す & 演算子を使うように更新された。ただしこれは意味を明確にするためであって、論理和を表す | 演算子などは型システムがサポートできるものではない(サポートするべきではない)ことが表明されている

Generics Manifesto のうちのいくつかは、すでに proposal として議論が進められており、大半は承認されている。

Standard Library

標準ライブラリに便利なメソッドを増やそうとするような proposal は多い。どれも一度くらいはほしいと思った機能ではないか。


さて、ここまでトピック毎に多くの proposal を見てきた。Swift 3.0 が非常に巨大なリリースであることに疑いの余地はない。とてもたくさんの点で改善される Swift 3.0 が待ち遠しいと思う。しかし同時に、既存のプロジェクトを Swift 3.0 にマイグレーションするのは骨が折れるだろう。

Swift が OSS になって約半年、信じられないスピードで変化を続ける Swift は、いまや広くコミュニティに受け入れられている。変化の早い Swift を使いこなすためには、Swift Evolution をよく観察しておくのが早道だ。


株式会社はてなでは、未来の Swift への興味が抑えきれないエンジニアを募集しています。

hatenacorp.jp

また、はてなサマーインターン2016では Swift を使ったモバイルアプリケーション開発が体験できます。

「はてなサマーインターン2016申し込み」はこちら

ふるってご応募ください。