読者です 読者をやめる 読者になる 読者になる

誰もが知りたいSequenceとCollectionのすべて | try! Swift Tokyo 2017 #tryswiftconf Day2-2 聞き起こし

twitter.com

SequenceとCollectionについて深く掘り下げてみましょう。LinkedListを実装することでSequenceとIteratorがどのように相互作用するかを見ていきます。この講演ではCollectionと関連するプロトコルと型(Index、Sliceable、MutableCollectionなど)がそれぞれどのように相互作用するかについて説明します。最終的にSequenceとCollectionについて知りたかったこと以上のことがわかるようになるでしょう。

誰もが知りたいSequenceとCollectionのすべて

f:id:niwatako:20170303103244j:plain

Swiftを扱う際に順番の整ったオブジェクトを使いたい場合99%Arrayになると思います。

入念に考えられたプロトコルヒエラルキーやそれ以外のコンポーネントの組み合わせで素晴らしい機能が整っています

f:id:niwatako:20170303103335j:plain

沢山資料は用意しています。25分で全てカバーします。

Sequenceプロトコルの上に全てがあります。Arrayとやり取りするバックボーンです。mapなど。

他のプロトコルははしごのように重なっているのでしたからみていきます。

f:id:niwatako:20170303103438j:plain

f:id:niwatako:20170303103440j:plain

Collection、BidirectionalCollectionまでご説明します。

Sequence

とてもわかり易いです。エレメントのリストで2つの重要な、有限である、そして一度しかいてレート出来ない(出来ても保証はない)ということです。

二つのコンポーネント、associatedtypeとmakeIterator()

f:id:niwatako:20170303103557j:plain

ItelatorProtocolはElementがnext()でイテレートしていく。

ItelatorProtocolはSequenceのベースに構築されています。

f:id:niwatako:20170303103638j:plain

リンクリストを構築してみたいと思います。

最初のエレメントが2つ目のエレメントを指し。。。。最後に至ります。

LinkList定義には私はenumを使うのが良いと思っています。

f:id:niwatako:20170303103718j:plain

indirect enum LinkedListNode<T> {
    case value(element: T, next: LinkedListNode<T>)
    case end
}

でもこれはmapなどは使えません。そのためにSequenceに対応します。

f:id:niwatako:20170303103828j:plain

f:id:niwatako:20170303103844j:plain

currentで代表されます

f:id:niwatako:20170303103929j:plain

これがnext関数

f:id:niwatako:20170303103941j:plain

値が戻されてnilだともう終わりです。

enumがあるのでいろんなことが出来ます。

f:id:niwatako:20170303104003j:plain

2つケースが有ります。

f:id:niwatako:20170303104013j:plain

次へ行くか終わりか。

nextで何をするか、currentをアップデートします。

これをSequenceに適用します。

f:id:niwatako:20170303104051j:plain

やらないくてはいけないことはSequence型に適合、forやmapが出来るようになります。

Iteratorがどう動くか

f:id:niwatako:20170303104140j:plain

Currentが最初の要素をポイントしています。

nextを呼び出すとCurrentが次の要素をポイントします。

f:id:niwatako:20170303104159j:plain

全てのSquenceを作りたければどうしたら良いのか

いくつのオブジェクトが合格したか確認したいときどうしたら良いでしょう。

f:id:niwatako:20170303104302j:plain

この関数をすべてのSequenceに適用したい

パラメータをcountにします

f:id:niwatako:20170303104331j:plain

forでcountしていく

f:id:niwatako:20170303104425j:plain

Userがadminなら1count up

もう一つ便利なのはEach Pair

f:id:niwatako:20170303104503j:plain

Autolayoutの制約を追加する時に使ったり出来ます。

f:id:niwatako:20170303104536j:plain

f:id:niwatako:20170303104616j:plain

zipを使っています。

f:id:niwatako:20170303104635j:plain

これは型消去です。

f:id:niwatako:20170303104713j:plain

引数によってSequenceのタイプが出てこない。

制約を自分たちで次第で実装します。

subSequence がSequenceであることを保証したい

f:id:niwatako:20170303104803j:plain

SubSequenceがあり、それがSequenceだと分かっているが、その中がまた同じタイプかわからない

そこで制約を加える

f:id:niwatako:20170303104834j:plain

煩雑ですがこれしか方法はない

Collection

f:id:niwatako:20170303104855j:plain

f:id:niwatako:20170303104911j:plain

すべて有限である、複数回イテレート出来る

f:id:niwatako:20170303104930j:plain

はじめと終わりのIndexがある。Indexがあるとsubscribeがある

f:id:niwatako:20170303105017j:plain

f:id:niwatako:20170303105047j:plain

f:id:niwatako:20170303105120j:plain

たいてい位置からCollectionを実装することはないが

ErrorCollectionを使いたい

f:id:niwatako:20170303105144j:plain

f:id:niwatako:20170303105200j:plain

f:id:niwatako:20170303105215j:plain

よくこれは使っています。Array出ないものをArray家のように振る舞わせます。

f:id:niwatako:20170303105234j:plain

bidirectionCollection

f:id:niwatako:20170303105245j:plain

コレクションを継承しています。前にも後ろにも戻れます。

一つ追加する必要があります。collectionにindex(before)を追加します。

f:id:niwatako:20170303105414j:plain

var last: Iterator.Element? {

}

lastは最後まで行って最後のエレメントを一つ戻ってあたいを返す。

3つを見てきました

f:id:niwatako:20170303105426j:plain

ランダムに行きたい要素に行けるCollection、コレクションの真ん中にある塊にアクセスできるCollectionなど

Swiftのドキュメントで見ることが出来ます

Q&A

SwiftのSequenceのassociatedTypeがIteratorだが他の言語ではElementになることが多い。何か良いことはあるのか?

IteratorがSwiftで表現力が増すということになると、何が良いか、Iteratorのときは内部で使われることが多いです。なので考えることはないですが、しかしそれ以外のときに、マニュアルで何か順番に見ていく時、たとえばいろんなページを遷移していく時、CollectionではなくIteratorを保持すれば良い。Nextを呼べば良い。Expressivenessを開けることが出来る。

ちょっと上手く伝わらなかったので後で行きます。

ほか