忙しい人向けの Embrace Swift type inference - #WWDC20

画像1

冒頭

以下の構成で見ていく。

画像2

Leveraging type inference

型推論とは、明示的な型指定を省略できる仕組み。ここでは x の型を指定していないが、コンパイラによって右辺の文字列リテラルから推論される。

画像3

型を明示的に指定するには「: (コロン)」のあとに指定するか・・・

画像4

as キーワードで指定する。

画像5

スムージーの一覧に検索機能を追加する例を見ていく。

画像7

現状のコードはこう。

画像7

まずは検索キーワードを保持するために @State なプロパティが必要。

画像8

次に List に似た FilteredList を作成する。これはフィルタ対象のプロパティを Key-path で受け取る引数 filterBy と、どの要素を含めるかを決めるクロージャ isIncluded を受け取る。

画像9

FilteredList のイニシャライザは簡潔だが型推論に大きく依存している。これを理解するために FilteredList の宣言を見ていく。

画像10

How type inference works in compiler

FilteredList は汎用的にするためにジェネリクスを利用している。ここでは3つのパタメータを導入したが、これはプレースホルダで、呼び出し元において具体的な型に置き換えられる。正式には「具体型(concrete types)」と呼ばれ、明示的に指定するか、コンパイラによって推論されて決定する。

画像11

イニシャライザの実装は以下のとおり。最後の引数で @ViewBuilder を指定しているが、これは SwiftUI の DSL として機能させるためのもの。

画像12

呼び出し元のコードを見ると、明示的な型指定はされておらずスッキリしていることが分かる。

画像13

明示的に指定すると以下のようになる。型推論はこれらのプレースホルダを自分で埋める代わりに、コードの文脈から自動的に埋める。

画像19

型推論はパズルのようなもので、ソースコードを手がかりにして欠けたピースを埋めていく。1つのピースを埋めると、また手がかりが増えて新たなピースを埋めることができる。

画像20

型推論の動きを見ていく。まず、引数 smoothies は既に [Smoothie] 型に決まっているため・・・

画像16

Element[Smoothie] に置き換えられる。

画像17

他の Element もすべて同じ型に置き換えられる。

画像18

同様に \Smoothie.titleString 型であるため・・・

画像19

FilterKey はすべて String に置き換えられる。

画像20

最後の RowContent は、クロージャ本体から SmoothieRowView に置き換えられる。

画像21

この一連のステップが、コンパイラによる型推論の戦略。書かれたコードを手がかりにしてステップを進め、各ステップの結果はそれ以降の手がかりとなる。

Using Swift and Xcode to fix compiler errors

しかし、手がかりを元に残りのピースを埋めようとしても、うまくハマらないケースがある。この場合はコードにエラーがあるということ。

画像22

例として、filterBy に \Smoothie.title の代わりに \Smoothie.isPopular を指定してしまったケースを考える。これは Bool 型であるため、FilterKey はすべて Bool に置き換えられるが・・・

画像23

Bool 型は hasSubstring というメソッドを持っていないため、

画像24

コンパイルエラーとなる。

画像25

私達はミスを犯すため、プログラミング言語やそのツールは人間としての限界を考慮して設計されていなければならない。Swift コンパイラはエラー追跡を型推論に統合することで、間違いを見つけやすくしている。

具体的には、型推論中に遭遇したエラー情報を記録しつつ、ヒューリスティックなエラー修正をして型推論を続行し、最後に収集したエラー情報を元に Fix-it やエラーメッセージを生成する。これは Swift 5.2 で導入され、Swift 5.3 ですべての式に対しても機能するようになった。

画像26

エラーメッセージは、コードの修正を手助けするペアプログラマのように設計されている。

画像27

具体的な例を見ていく。検索のためにテキストフィールドを追加したが、以下のようなエラーになった。

画像28

これはバインディングではなく値を渡すというミスによるものだが、コンパイラがそれを理解しているため Fix ボタンで修正できる。

画像29

次に FilteredList を追加すると以下のエラーになった。ここでは Identifiable を利用していないので若干混乱するかもしれない。

画像30

しかし、新しいエラー追跡の仕組みによって Issue Navigator から、型推論中に何が起こっていたのかを確認できる。今回は ElementSmoothie という具体型(concrete-type)であると推論されていたのが分かる。

画像31

宣言を確認すると、Element は Identifiable プロトコルに準拠していなければならないことが分かる。今回はそれを忘れていたので、Smoothie を Identifiable に準拠させることで解決する。

画像32

Option + Click によるクイックヘルプで、実際にどのような型に推論されたのかを確認できる。

画像33

最後にプレビュー用のコードを追加して、期待どおりに動作していることを確認できた。

画像34

まとめ

・SwiftUI のコードは型推論に大きく依存している。
・型推論はソースコードをヒントにして、省略された部分を埋める。
・統合されたエラートラッキングはより多くのエラー情報を収集する。

画像35

より詳細を知りたい人は New Diagnostic Architecture Overview も参照のこと。

画像36

免責

・本記事は公開情報のみに基づいて作成されています。
・要約(意訳)のみなので、詳細はセッション動画をご確認ください。

関連記事


役に立った記事などありましたらサポート頂けると嬉しいです。