Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

リテラルと型の話 #__swift__

3,764 views

Published on

2015-12-20 に開催された『集まれ! Swift 好き!Swift 愛好会』で話した資料です。補足事項を少し追加してます。

Published in: Software
  • Be the first to comment

リテラルと型の話 #__swift__

  1. 1. EZ-NET 熊⾕友宏 http://ez-net.jp/ 2015.12.20 @ 集まれ Swift 好き!Swift 愛好会 リテラルと型の話 Swift カジュアルプログラミング Swift 2.1.1
  2. 2. 熊谷友宏 EZ-NET http://ez-net.jp/ @es_kumagai CodePiece iOS, OS X, Apple Watch アプリ ソースコードを Twitter と Gist に同時投稿できる。 いつもの電卓 計算式も見える電卓アプリ。 watchOS 1 対応 音で再配達ゴッド 簡単操作で 再配達の申し込み。 EZ-NET IP Phone iPhone でひかり電話を使う。 自宅 LAN からの利用専用
  3. 3. CodePiece for OS X 勉強会を楽しむアプリ ソースコードを Twitter と Gist に同時投稿できる
 勉強会で知見をみんなと共有したい時とかに便利! できること #__swift__
  4. 4. 熊谷友宏 EZ-NET http://ez-net.jp/ @es_kumagai 横浜 iPhone 開発者勉強会 #yidev 勉強会 わいわい・ゆるく、iPhone 開発者の
 みんなで楽しく過ごすのが目的の会 【 横浜・馬車道 】 カジュアル Swift 勉強会 #cswift ゆるくみんなで Swift を語らえる場を
 作りたくて始めた会 【 横浜・青葉台 】 第22回を 2016-03-05 に開催予定 第4回を 2015-12-26 に開催
  5. 5. 熊谷友宏 EZ-NET http://ez-net.jp/ @es_kumagai Xcode 5 徹底解説 MOSA 書籍 / 登壇 Xcode 5 の全機能を
 徹底的に解説した本 OSX/iOS 系の歴史深い
 有料会員制の勉強会 紙版は絶版、電子書籍は販売中 秀和システム 10x-Eng.com で取扱予定 Xcode 7 でも役立つはず 法人会員も多数
  6. 6. 混乱しがちな? リテラルの話
  7. 7. リテラルの話 1. リテラルの基礎を知り 2. リテラルの仕組みを把握して 3. リテラルの実際の動きを掌握する 構成
  8. 8. リテラル 概要
  9. 9. リテラル ▶ コードで値を書くのに使う ▶ 具体的な内容を記述する 概要 "Swift" 2.1
  10. 10. リテラル ▶ 整数リテラル ▶ 小数点数リテラル ▶ 真偽値リテラル ▶ 文字列リテラル ▶ nil リテラル ▶ 配列リテラル ▶ 辞書リテラル 種類 … 3 … 3.1 … true, false … "STRING" … nil … [ value, ... ] … [ key : value, ... ]
  11. 11. リテラル【 Literal 】 ▶ 書いたまんま、というのを表す言葉 ▶ 高級言語の用語で、コードに直接記載された値 即値【 Immediate 】 ▶ 直接的なものを表す言葉 ▶ アセンブラ用語で、コードに直接埋め込んだデータ 言葉が違うからリテラルを即値と訳すのは誤りとする説も ありますが、訳として間違いとも言えない気もします。 【補足】リテラルと即値
  12. 12. リテラルを書く
  13. 13. リテラルの書式 (1/7) ▶ 2進数、8進数、10進数、16進数で表記可能 ▶ 各数字の後ろに自由に _ を挿入できる 整数リテラル 200 // 10 進数 0xc8 // 16 進数 0o310 // 8 進数 0b11001000 // 2 進数 20_000_000 // _ は無視される
  14. 14. リテラルの書式 (2/7) ▶ 10進数、16進数で表記可能 ▶ 各数字の後ろに自由に _ を挿入できる 小数点数リテラル 2.10 // 10進数 1.25e-4 // 10進数 … 1.25 × 10-4 0x15.8p3 // 16進数 … 0x15.8 × 23 1.001_001_e-8 // _ は無視される
  15. 15. リテラルの書式 (3/7) ▶ 真か偽かの2種類だけ 真偽値リテラル true // 真を表現 false // 偽を表現
  16. 16. リテラルの書式 (4/7) ▶ 引用符で括って文字列を表現 ▶ 特別な文字も挿入可能 文字列リテラル "Swift" // Swift ""Swift"" // "Swift" "Header:tText" // Header: Text "!u{20DD}" // ! ⃝
  17. 17. リテラルの書式 (5/7) ▶ 無 を表現 nil リテラル nil // 無
  18. 18. リテラルの書式 (6/7) ▶ 複数の要素を持つことを表現 ▶ 各要素は自由に指定 配列リテラル [ 1.5, val, "STR" ] // 3つの要素を持つ配列 [] // 何も要素を持たない配列
  19. 19. リテラルの書式 (7/7) ▶ 複数の要素を持つことを表現 ▶ 各要素は キー と 値 の対で自由に指定 辞書リテラル [ "A": 10, "B": 20 ] // 2つの要素を持つ辞書 [ : ] // 何も要素を持たない辞書
  20. 20. リテラルを使う
  21. 21. リテラルの使い方 ▶ 変数に入れて使う コード内にリテラルを書く let name = "Swift" let version = 2.1
  22. 22. リテラルの大事なところ 基礎
  23. 23. リテラルに型はない
  24. 24. リテラルの大事なところ ▶ リテラルだけでは値はできない リテラル自体に型はない let value = nil Type of expression is ambiguous with more context
  25. 25. リテラルを型に嵌める必要がある
  26. 26. リテラルの大事なところ ▶ リテラルが型の値に変換される ▶ 前後関係から適切な型が決定される 型を明記して値にする let value = nil as Int? let value: Int? = nil
  27. 27. でも、型を明記しないで リテラルを使えていたような? let name = "Swift" let version = 2.1
  28. 28. リテラルの既定の型
  29. 29. リテラルの大事なところ ▶ リテラルは型を明示して値にする ▶ 明示されないときは 既定の型 とみなす リテラルを型に嵌める // 整数リテラルが Double 型に決まる let value = 10 as Double // 整数リテラルが Int 型とみなされる let value = 10 Double 型 Int 型
  30. 30. 型が明示されないときの既定の型 リテラルの大事なところ ▶ 整数リテラル ▶ 小数点数リテラル ▶ 真偽値リテラル ▶ 文字列リテラル ▶ nil リテラル ▶ 配列リテラル ▶ 辞書リテラル … Int 型 … Double 型 … Bool 型 … String 型 … なし … Array 型 … Dictionary 型
  31. 31. リテラルの大事なところ ▶ 前後関係からも型が推論される ▶ たとえば、代入や計算 前後関係からも型が決まる // Double 型の変数があるとき let value:Double = 10 // 整数リテラルが Double 型とみなされる let answer = value * 10 Double 型
  32. 32. リテラルの大事なところ ▶ 前後関係からも型が推論される ▶ たとえば、関数の引数 前後関係からも型が決まる // Double 型を受け取る関数があるとき func doSomething(value:Double) { } // 渡したリテラルが Double 型とみなされる doSomething(10) Double 型
  33. 33. 型が既に決められている場合はそれに従う let array: [Int] = [10, 20, 30] 内容から [Double] 型と推論 let array = [3.01, 3.12, 3.23, 3.34] オブジェクト型は継承関係も考慮して推論 let array = [りんご(), みかん(), ぶどう()] プロトコルの準拠性や継承関係では推論されない 【余談】配列リテラルからの型推論 [Int] 型 [Double] 型 [くだもの] 型
  34. 34. リテラルを型に嵌める仕組み 実践
  35. 35. 型がリテラルを引き受ける仕組み
  36. 36. ▶ 型がリテラルの受け入れを表明する ▶ 対応リテラルは LiteralConvertibleで決定 // IntegerLiteralConvertible を表明していれば enum MyVariant : IntegerLiteralConvertible { } // 整数リテラルを受け入れられる let value: MyVariant = 10 リテラルを受け入れられる型 型がリテラルを引き受ける
  37. 37. ▶ イニシャライザーでリテラルを受け取る ▶ 受け取った値を適切なデータに変換する enum MyVariant : IntegerLiteralConvertible { case IntegerValue(Int) case FloatingPointValue(Double) init(integerLiteral value: Int) { self = .IntegerValue(value) } } 型が責任を持って値を作る 型がリテラルを引き受ける
  38. 38. 受け入れ表明で使うプロトコル 型がリテラルを引き受ける ▶ 整数リテラル ▶ 小数点数リテラル ▶ 真偽値リテラル ▶ 文字列リテラル ▶ nil リテラル ▶ 配列リテラル ▶ 辞書リテラル … IntegerLiteralConvertible … FloatLiteralConvertible … BooleanLiteralConvertible … StringLiteralConvertible … NilLiteralConvertible … ArrayLiteralConvertible … DictionaryLiteralConvertible
  39. 39. 定義 protocol IntegerLiteralConvertible { typealias IntegerLiteralType init(integerLiteral value: IntegerLiteralType) } 整数リテラルを受け取るときに使うイニシャライザーが 規定されています。これに準拠した型は整数リテラルを 受け入れられる型になります。 【補足】IntegerLiteralConvertible
  40. 40. 定義 protocol StringLiteralConvertible : ExtendedGraphemeClusterLiteralConvertible { typealias StringLiteralType init(stringLiteral value: StringLiteralType) } protocol ExtendedGraphemeClusterLiteralConvertible : UnicodeScalarLiteralConvertible { typealias ExtendedGraphemeClusterLiteralType init(extendedGraphemeClusterLiteral value: ExtendedGraphemeClusterLiteralType) } protocol UnicodeScalarLiteralConvertible { typealias UnicodeScalarLiteralType init(unicodeScalarLiteral value: UnicodeScalarLiteralType) } 文字列リテラルを受け取るときに使うイニシャライザーが 規定されています。複数のプロトコルを継承しています。 init(stringLiteral:) 以外の使われ方を教えてください ! 【補足】StringLiteralConvertible
  41. 41. リテラルと型の関係
  42. 42. ▶ 型がリテラルを引き受ける ▶ リテラル自体に型はない おさらい リテラルと型の関係 // リテラルは、いろんな型に染まる let value: Int = 10 let value: UInt64 = 10 let value: Double = 10 let value: NSNumber = 10
  43. 43. 関係性から見えてくること リテラルと型の関係 nil は Optional 型?Q. Optional 型が nil を空として扱うA.
  44. 44. 関係性から読めてくること リテラルと型の関係 true は Bool型?Q. Bool型が true を真として扱うA. NSNumber型が真と扱っても良いA.
  45. 45. ▶ リテラルをどう扱うかは型の責任 ▶ リテラルの意味を尊重することは重要 // 整数リテラルを 32 bit 整数 として扱う let number: Int32 = 100 // nil リテラルを 何もない として扱う let value: String? = nil // 配列リテラルを オプションセット として扱う let options: UIViewAutoresizing = [.FlexibleWidth, .FlexibleHeight] リテラルの扱いは型の裁量で決まる リテラルと型の関係
  46. 46. 整数リテラルは Int 型?Q.
  47. 47. たとえば … リテラルから受け取る値 型の内容がUInt64で表現されるとき リテラルがInt型だと表現しきれない
  48. 48. ▶ 型の内容が UInt64 で表現されるとき ▶ リテラルが Int 型では表現しきれない struct UserID : IntegerLiteralConvertible { var value: UInt64 init(integerLiteral value: Int) { self.value = UInt64(value) } } リテラルを 64 bit 符号なし整数で扱いたい リテラルから受け取る値
  49. 49. リテラルには型がない💡
  50. 50. ▶ リテラルは任意の型で受け取れる ▶ ただし、互換性のあるものに限る struct UserID : IntegerLiteralConvertible { var value: UInt64 init(integerLiteral value: UInt64) { self.value = value } } リテラルを 64 bit 符号なし整数で受け取る リテラルから受け取る値
  51. 51. ▶ 小さい型でも受け取れる ▶ 範囲を超えると ビルドタイム でエラー struct Word : IntegerLiteralConvertible { init(integerLiteral value: UInt8) { … } } let word1: Word = 255 let word2: Word = 300 リテラルの値の範囲を絞れる リテラル変換で受け取る値 Integer literal '300' overflows when stored into 'UInt8'
  52. 52. 定義 struct MyIntegerLiteral : _BuiltinIntegerLiteralConvertible { var value: Int8 init(_builtinIntegerLiteral value: _MaxBuiltinIntegerType) { self.value = Int8(_builtinIntegerLiteral: value) } } 使用 struct MyStruct : IntegerLiteralConvertible { init(integerLiteral value: MyIntegerLiteral) { } } このようにするとリテラルの値を自作の型で受け取れます。 ただし、ビルド時のオーバーフロー検出は行われません。 【余談】IntegerLiteralType の互換性
  53. 53. リテラルの動きを捉える 演習
  54. 54. リテラルから値を生成する 1/5
  55. 55. ▶ リテラルに型を指定して値を作る ▶ 変換イニシャライザーが呼び出される enum MyVariant : IntegerLiteralConvertible { } // A. 型を明記した変数にリテラルを入れる方法 let value: MyVariant = 200 // B. リテラルに型を明記する方法 let value = 200 as MyVariant リテラルから値を生成する リテラルの動きを捉える
  56. 56. 型 リテラルから値を生成する リテラル 型を明示 変換イニシャライザー 値 リテラルの動きを捉える
  57. 57. 型を複数のリテラルに対応する 2/5
  58. 58. ▶ 複数のリテラルコンバーティブルに準拠 ▶ それぞれのリテラルを受容可能になる // 型が複数のリテラルを受け入れるときに enum MyVariant : IntegerLiteralConvertible, FloatLiteralConvertible { } // 対応するどのリテラルからも生成可能 let value1: MyVariant = 200 let value2: MyVariant = 150.8 型を複数のリテラルに対応する リテラルの動きを捉える
  59. 59. 型 型を複数のリテラルに対応する リテラルの動きを捉える 整数 リテラル 型を明示 整数用の変換イニシャライザー 値 小数点数用の変換イニシャライザー
  60. 60. 値をリテラルと比較する 3/5
  61. 61. ▶ リテラルと直接的に比較できる ▶ 型が比較可能なことが条件 enum MyVariant : IntegerLiteralConvertible, Equatable { } let value: MyVariant = 200 // リテラルと直接的に比較可能 if value == 300 { } 値をリテラルと比較する リテラルの動きを捉える
  62. 62. 値をリテラルと比較する リテラルの動きを捉える リテラル==値 同じ型での比較原則 値 型 変換イニシャライザー 型を推論
  63. 63. 関数の引数にリテラルで渡す 4/5
  64. 64. ▶ リテラルを直接引数に渡せる ▶ 目的の型の値へ暗黙的に変換される // 型を引数で受け取る関数に func calculate(value: MyVariant) { } // 対応するリテラルを直接的に渡せる calculate(120) 関数の引数にリテラルで渡す リテラルの動きを捉える
  65. 65. 関数の引数にリテラルで渡す リテラルの動きを捉える リテラル 値 関数(value:型) 型 変換イニシャライザー 型を推論
  66. 66. 列挙型のRaw値で自作の型を使う 5/5
  67. 67. ▶ リテラル対応の型を Raw 値に使える ▶ 使えるリテラルは整数、小数、文字列のみ // 列挙子の値はリテラルで指定する enum Coefficient : MyVariant { case Treble = 3 case Halve = 0.5 } // Raw 値を MyVariant 型で取得できる Coefficient.Treble.rawValue 列挙型のRaw値で自作の型を使う リテラルの動きを捉える
  68. 68. 列挙型のRaw値で自作の型を使う リテラルの動きを捉える Raw 値 列挙型 Raw 型 変換イニシャライザー 列挙子A Raw 型 リテラル 列挙子B リテラル rawValue
  69. 69. 【補足】列挙型の Raw値で使えるリテラル ▶ 整数リテラル ▶ 小数点数リテラル ▶ 文字列リテラル 複数種類のリテラルを受け入れられる型を Raw 型に指定すると Raw 値に複数のリテラルを混ぜて指定できるようになります。
  70. 70. 隠しリテラル ? おまけ
  71. 71. カラーリテラル Color Literal
  72. 72. import UIKit let color: UIColor = [#Color(colorLiteralRed: 0.6587, green: 1.0000, blue: 0.6987, alpha: 1.0000)#] 概要 カラーリテラル [#Color(colorLiteralRed: R, green: G, blue: B, alpha: A)#]
  73. 73. protocol _ColorLiteralConvertible { init(colorLiteralRed: Float, green: Float, blue: Float, alpha: Float) } Literal Convertible カラーリテラル extension NSColor : _ColorLiteralConvertible { } extension UIColor : _ColorLiteralConvertible { }
  74. 74. Playground で使う カラーリテラル 1. コード行に [#Color#] と書く 2. インラインに 箱  が描かれる 3. 箱をダブルクリックして カラーピッカー で選べる Playground
  75. 75. Playground での使用例 カラーリテラル Playground
  76. 76. カラーパレットからの入力も可能 カラーリテラル Playground カーソル行へのドロップで入力
  77. 77. カラーパレットは Edit メニューから表示 カラーリテラル Playground
  78. 78. 画像リテラル Image Literal
  79. 79. import UIKit let image: UIImage = [#Image(imageLiteral: "Swift.png")#] 概要 画像リテラル [#Image(imageLiteral: PATH)#]
  80. 80. protocol _ImageLiteralConvertible { init(imageLiteral: String) } Literal Convertible 画像リテラル extension NSImage : _ImageLiteralConvertible { } extension UIImage : _ImageLiteralConvertible { }
  81. 81. Playground で使う 画像リテラル A. コード行に直接書く [#Image(imageLiteral: "Swift.png")#] Playground OR B. コードに画像を直接ドロップする
  82. 82. Playground での使用例 画像リテラル Playground
  83. 83. ファイルリテラル File Reference Literal
  84. 84. import Foundation let path: NSURL = [#FileReference( fileReferenceLiteral: "main.mm")#] 概要 ファイルリテラル [#FileReference(fileReferenceLiteral: PATH)#]
  85. 85. protocol _FileReferenceLiteralConvertible { init(fileReferenceLiteral: String) } Literal Convertible ファイルリテラル extension NSURL : _FileReferenceLiteralConvertible { }
  86. 86. Playground で使う ファイルリテラル A. コード行に直接書く [#FileReference(fileReferenceLiteral: "main.mm")#] Playground OR B. コードにファイルを直接ドロップする
  87. 87. Playground での使用例 ファイルリテラル Playground
  88. 88. 型とリテラルの話 以上
  89. 89. まとめ リテラルと型の話 1. リテラルを書く・リテラルを使う 2. リテラルの大事なところ リテラルに型はない リテラルを型に嵌める リテラルの既定の型 3. リテラルを型に嵌める仕組み 型がリテラルを受け入れる リテラルと型の関係 4. リテラルの動きを捉える 5. 隠しリテラル?

×