この記事はSwift Tweets 2017 Spring - connpassにて「Swift Standard Library相関図」というタイトルで発表したものにたくさん加筆したり修正したものです。
3〜4個くらいのProtocol同士の継承関係のツリーなら各所の発表でよく見るのですが、どういうわけか全体図を見たことがないので作ることにしました。
Swift Standard Libraryとは
The Swift standard library defines a base layer of functionality for writing Swift programs
import Foundation
しなくてもSwiftが素で使えるシンボルたち。
ドキュメントは Swift Standard Library | Apple Developer Documentation
実装は swift/stdlib/public/core at master · apple/swift
公式ドキュメントにある各シンボルのページについて、以下の点については注意が必要である。
Protocol → Protocol の継承関係が被継承側のページには書かれていない
Structure → Protocolの関係は継承側のConforms Toと被継承側のAdopted Byの両方のページに書かれている。Protocol → Protocolも継承側のInherits fromに書かれている。被継承側のAdopted Byには書かれていない。
struct Int → protocol SignedInteger → protocol Integer → protocol Strideable → protocol Comparable あたりを見るとこの現象がわかりやすい。
全ての継承関係が書かれていない(?)
読み間違えかと思ったが、Relationshipsの欄のConforms To/Inherits From/From Protocol等を全部合わせてもやっぱり何か足りない(後で紹介するUnsafeRawBufferPointer.Iterator
など)。理由があるのか?誰か知っていたら教えてください。
あとはシンボル名に <wbr>
が混じっていることに気がつかなくてグラフ作成時に意図した挙動にならず悩んだとかそのくらい。
完成図
とても重たくて載せられないので、ここにはdot言語へのリンクと超縮小図のみ載せる。
公式ドキュメントを愚直にスクレイピングして作ったので先述の「公式がちゃんと網羅していない」問題に思い切り引っかかり、正確な図ではない。
brew install graphviz
して dot
コマンドを正しく叩くと出力される。
青ノードがEnumeration、緑ノードがClass、灰ノードがProtocol、赤ノードがStructureのシンボルを指す。
見やすくするため、
Custom(Debug)?StringConvertible
/ CustomPlaygroundQuickLookable
/ Expressible.+
のノードとそこへ向かうエッジは掲載していない。
Equatable
/ Comparable
/ Hashable
/ CustomReflectable
へのエッジを薄くした。
Protocol間のエッジを太くした。
継承関係を持つProtocolのノードを大きくした。
眺めてみる
Structure / Class / Enumeration / Protocol
Structureは140個、Classは1個、Enumerationは12個、Protocolは48個ある。もちろん今回の主役はProtocolである。
ClassとEnumerationは数が少ないので、せっかくなので列挙してみる。
Class:
Enumeration:
- CommandLine*
- FloatingPointClassification
- FloatingPointRoundingRule
- FloatingPointSign
- ImplicitlyUnwrappedOptional
- MemoryLayout*
- Mirror.AncestorRepresentation
- Mirror.DisplayStyle
- Never*
- Optional
- PlaygroundQuickLook
- UnicodeDecodingResult
これ以外はStructureかProtocolと覚えておけばよい。Enumには Optional
( .none
/ .some
)のようにちゃんと列挙しているものと、 Never
のように我々がインスタンスを取るようなものではないもの(*で印をつけたもの)が混ざっている。
Equatable / Comparable
おなじみ Equatable
/ Comaparable
。あちこちから継承されている。
位置としてはここ。
StrideableやSequenceのツリーを綺麗に出すために犠牲になってもらったのでノードが遠くなった。
Collection / Sequence
Sequence
を頂点とするツリー。 IteratorProtocol 自体は Sequence
ツリーの一員ではないが、各Iterator が Sequence
を実装している。
Strideable
Comparable
な連続する値を指す。UnsafePointer群と整数と浮動小数が連なる。
CVarArg
C言語の可変長引数で扱える型を指す。公式ドキュメントのページのAdopted ByにはFoundationやナントカKit所属のシンボルが無数に並んでいる。
SSL内では
- Array
- AutoReleasingUnsafeMutablePointer
- Dictionary
- Int / Int64 / Int32 / Int16 / Int8
- OpaquePointer
- Set
- String
- UInt / UInt64 / UInt32 / UInt16 / UInt8
- UnsafeMutablePointer
- UnsafePointer
のみ。
Pointer
各Pointerはそれぞれ役割が異なる。よってくっついているProtocolも異なる。
AutoreleasingUnsafeMutablePointer
やCVaListPointer、OpaquePointer
はObjCやC関係のポインタである。ManagedBufferPointerは名の通り連続領域にアクセスするためのもの。
UnsafePointerについてはProtocolツリーの観点から2種類に分けられる。 Strideable
なUnsafePointerと Collection
なUnsafePointerである。
Strideable
なUnsafePointer
UnsafePointer
- UnsafeMutablePointer
- UnsafeRawPointer
- UnsafeMutableRawPointer
Collection
なUnsafePointer
Buffer、つまりこちらは連続領域を指す。
孤立しているシンボル
Unicodeのデコード/エンコードは他から独立している。
- protocol UnicodeCodec / struct UTF-8 / struct UTF-16 / struct UTF-32
以下は(少なくともSSL内では)完全に継承関係を持たないもの。
- MirrorPath
- Error: NSError(Foundation)とCFError(CoreFoundation)から継承されている
- AnyObject
PlaygroundQuickLook
Never
Mirror.DisplayStyle
Mirror.AncestorRepresentation
MemoryLayout
FloatingPointSign
FloatingPointRoundingRule
FloatingPointClassification
CommandLine
ManagedBuffer
- Unmanaged
なお、ドキュメント上Conforms Toの欄がないことになっている以下のシンボルについては、実際はちゃんと継承している模様。
-
UnsafeRawBufferPointer.Iterator / UnsafeMutableRawBufferPointer.Iterator(swift/UnsafeRawBufferPointer.swift.gyb at master · apple/swift):
IteratorProtocol
,Sequence
-
String.UnicodeScalarView.Iterator(swift/StringUnicodeScalarView.swift at master · apple/swift):
IteratorProtocol
-
String.UTF16View.Indices
(swift/StringUTF16.swift at master · apple/swift):BidirectionalCollection
今回省略したシンボル
グラフを描くにあたり犠牲になったのは以下。
- ExpressibleByArrayLiteral / ExpressibleByBooleanLiteral / ExpressibleByDictionaryLiteral / ExpressibleByExtendedGraphemeClusterLiteral / ExpressibleByFloatLiteral / ExpressibleByIntegerLiteral / ExpressibleByNilLiteral / ExpressibleByStringLiteral / ExpressibleByUnicodeScalarLiteral
- CustomStringConvertible / CustomDebugStringConvertible
- CustomPlaygroundQuickLookable
ExpressibleBy.+Literal
はナントカ型で対象の型をイニシャライザできることを示す。Custom(Debug)?StringConvertible
と CustomPlaygroundQuickLookable
はそれぞれデバッグ用に便利なプロパティをつけるもの。
まとめ
公式ドキュメントに書いてあることが全部ではない。