>100 Views
January 20, 16
スライド概要
2016/01/20 に開催された『集まれSwift好き!Swift愛好会#3』で、前回の勉強会で話した、リテラルと型の話を受けて広がった続きの話、String Interpolation の概要的なところについてお話ししました。
※ Docswell での公開に移行する直前の Slideshare での閲覧数は 4,490 でした。
正統派趣味人プログラマー。プログラミングとは幼馴染です。
リテラルと型の 続きの 話 String Interpolation 2016.01.20 @ 集まれ Swift 好き!Swift 愛好会 #3 EZ-NET 熊⾕友宏 Swift 2.1.1 http://ez-net.jp/
謹賀新年 2016 .01 本年も素敵な年になりますよう ⼼よりお祈り申し上げます
熊谷友宏 @es̲kumagai EZ-NET http://ez-net.jp/ 勉強会 横浜 iPhone 開発者勉強会 カジュアル Swift 勉強会 【 横浜・馬車道 】 #yidev 【 横浜・青葉台 】 #cswift わいわい・ゆるく、iPhone 開発者の みんなで楽しく過ごすのが目的の会 ゆるくみんなで Swift を語らえる場を 作りたくて始めた会 第22回を 2016-03-05 に開催予定 第5回を 2016-02-06 に開催予定
熊谷友宏 @es̲kumagai EZ-NET http://ez-net.jp/ 書籍 / 登壇 Xcode 5 徹底解説 MOSA Xcode 5 の全機能を 徹底的に解説した本 OSX/iOS 系の歴史深い 有料会員制の勉強会 Xcode 7 でも役立つはず 法人会員も多数 紙版は絶版、電子書籍は販売中
熊谷友宏 @es̲kumagai EZ-NET http://ez-net.jp/ iOS, OS X, Apple Watch アプリ CodePiece いつもの電卓 ソースコードを Twitter と Gist に同時投稿できる。 計算式も見える電卓アプリ。 watchOS 1 対応 音で再配達ゴッド EZ-NET IP Phone 簡単操作で 再配達の申し込み。 iPhone でひかり電話を使う。 自宅 LAN からの利用専用
CodePiece for OS X 勉強会を楽しむアプリ ソースコードを Twitter と Gist に同時投稿できる 勉強会で知見をみんなと共有したい時とかに便利! できること #̲̲swift̲̲
リテラルと型の 続きの話
前回のあらすじ @ 集まれ Swift 好き!Swift 愛好会 #2
前回のあらすじ リテラルとは ▶ コードで値を書くのに使う ▶ 具体的な内容を記述する "Swift" 2.1
前回のあらすじ 要点 1. リテラルに型はない 2. 型がリテラルを引き受ける
前回のあらすじ 要点 (1/2) Q. リテラルに型はない A. リテラルはいろんな型に染まる let value: Int = 10 let value: UInt64 = 10 let value: Double = 10 let value: NSNumber = 10
前回のあらすじ 要点 (2/2) Q. 型がリテラルを引き受ける A. Literal Convertible プロトコル struct MyValue : IntegerLiteralConvertible { init(integerLiteral value: Int) { } }
前回のあらすじ リテラルの種類 ▶ 整数リテラル … 3 ▶ 小数点数リテラル … 3.1 ▶ 真偽値リテラル … true, false ▶ 文字列リテラル … "STRING" ▶ nil リテラル … nil ▶ 配列リテラル … [ value, ... ] ▶ 辞書リテラル … [ key : value, ... ]
前回のあらすじ リテラルと型の関係性 Q. true は Bool 型? A. A. Bool 型が true を真 として扱う NSNumber 型も真 として扱う let value: Bool = true let value: NSNumber = true
着目したいところ
文字列リテラル "Swift"
文字列リテラル 概要 ▶ 引用符で括って文字列を表現 ▶ 特別な文字も挿入可能 "Swift" // Swift "\"Swift\"" "Header:\tText" "!\u{20DD}" // "Swift" // Header: Text // ! ⃝
こんな書き方もできる "Swift \(version)"
文字列リテラル 値を挿入できる文字列表現 Q. "Swift \(version)" と書くと? A. 変数が実際の値に差し替えられる let version = 2.1 let text = "Swift \(version)" print(text) Swift 2.1
違和感
文字列リテラル リテラルに値を挿入できる? 1. リテラルに型はない…? 2. 型がリテラルを引き受ける…? 具体的な 値じゃない… リテラルに 型が混ざる? リテラル自身が 振る舞えるの? let text: String = "Swift \(version)" リテラル自身が 埋め込むの? 埋め込みなんて 想定してた…? 本当に型が 受け入れてる? 結果を返す 関数みたい…
能動的に動けすぎ…?
文字列リテラル 値を挿入できる文字列表現 Q. 本当にリテラルなのか? A. 試してみるしかないでしょう!
値を挿入した文字列 リテラルなのか確かめてみる 1. リテラルを受け入れる型を作って、 struct MyValue:StringLiteralConvertible { } 2. 代入する。 let version = 2.1 let value: MyValue = "Swift \(version)" Cannot convert value of type 'String' to specified type 'MyValue'
( ̄▽ ̄)
String Interpolation 文字列補間構文
The Swift Programming Language Swift uses string interpolation to include the name of a constant or variable as a placeholder in a longer string, and to prompt Swift to replace it with the current value of that constant or variable. Wrap the name in parentheses and escape it with a backslash before the opening parenthesis: println("The current value of friendlyWelcome is \(friendlyWelcome)")
String Interpolation 要点 ▶ 文字列の中に値を埋め込む仕組み ▶ \(value) という書式で埋め込む // value の値は "Swift 2.1" になる let version = 2.1 let value = "Swift \(version)"
String Interpolation 自由度の高い書式 ▶ 計算式も埋め込み可能 ▶ メソッド実行や末尾クロージャー使用も可能 "\(values)" "\(values.count)" "\(values.contains("2"))" "\(values.map { $0 * 2 } .reduce(0, combine: +))"
String Interpolation を想定した プロトコルも存在
プロトコル StringInterpolationConvertible ▶ 型が String Interpolation を 受け入れることを表明するプロトコル ▶ 複雑な書式をパーツ毎に分解して変換する protocol StringInterpolationConvertible { init(stringInterpolation strings: Self...) init<T>(stringInterpolationSegment expr: T) }
StringInterpolationConvertible 必須の実装 1. init<T>(stringInterpolationSegment: T) String Interpolation の各パーツを 順に受け取って自身の型に変換する 2. init(stringInterpolation: Self. . .) 各パーツを変換した値の配列から 最終的な値 を組み立てる
StringInterpolationConvertible 変換の流れ "Language_\(lang)_Version_\(ver)" 型 "Language_" lang "_Version_" ver "" init<T>(stringInterpolationSegment:) Array<型> 値 値 値 値 値 init(stringInterpolation:) 値
StringInterpolationConvertible 変換処理はオーバーロード可能 "Language_" lang "_Version_" ver "" init<T:Any>(stringInterpolationSegment:T) init<T:LanguageType>(stringInterpolationSegment:T) init(stringInterpolationSegment:String) Array<型> 値 値 値 値 値
String Interpolation 対応 自作の型を対応させる
String Interpolation 対応 目標 1. 型をString Interpolation に対応 2. 整数値は3桁区切りの文字列で表現 3. 整数値以外は文字列で表現 4. 各パーツをまとめて完成
String Interpolation 対応 (1/4) 型を String Interpolationに対応 ▶ 型でString Interpolation の受け入れを表明 ▶ StringInterpolationConvertible を適用 struct FormattedString : StringInterpolationConvertible { // このプロパティで文字列を表現 var value: String
String Interpolation 対応 (2/4) 整数値は3桁区切りの文字列で表現 ▶ 整数型の値を変換する処理 ▶ 自身の型で3桁区切りの文字列を表現 struct FormattedString : StringInterpolationConvertible { // 整数型を受け取った場合は、3桁区切りの文字列にする init<T:IntegerType>(stringInterpolationSegment expr:T) { let value = NSNumber(longLong: expr.toIntMax())! let formatter = NSNumberFormatter() formatter.numberStyle = .DecimalStyle self.value = formatter.stringFromNumber(value)
String Interpolation 対応 (3/4) 整数値以外は文字列で表現 ▶ 整数型以外の値を変換する処理 ▶ 自身の型に そのまま文字列で表現 struct FormattedString : StringInterpolationConvertible { // 整数型以外を受け取った場合は、そのまま文字列にする init<T>(stringInterpolationSegment expr: T) { self.value = String(expr) }
String Interpolation 対応 (4/4) 各パーツをまとめて完成 ▶ 最後に変換済みの全パーツを取得 ▶ それらを使って自身の型を再構築 struct FormattedString : StringInterpolationConvertible { // 変換済みの全てのパーツを文字列として連結して、完成 init(stringInterpolation strings: FormattedString...) { self.value = strings.reduce("") { $0 + $1.value } }
完成
String Interpolation 対応 完成した型を使う ▶ String Interpolationを記載 ▶ それが自作型であることを明記 let version = 2000 let string: FormattedString = "Windows \(version)" print(string.value) // 実行結果 Windows 2,000
リテラルと型の続きの 話 おしまい
リテラルと型の続きの話 まとめ 1. 前回のあらすじ ✓ リテラルとは ✓ リテラルに型はない ✓ 型がリテラルを引き受ける 2. 着目したいところ ✓ 文字列に値を挿入できる ✓ これって本当にリテラル? 3. String Interpolation(文字列補間構文) ✓ 文字列に値を挿入できる表現 ✓ 自作の型を 文字列補間構文 に対応させる