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

2015/3/29 Developers.IO 2015 Developers Day D-1 Session資料

続・ゲンバのSwift

  1. 1. Developer Day 続・ゲンバのSwift 1 D-1 安達 勇一 クラスメソッド株式会社 Ⓒ Classmethod, Inc. 2015年03月29日 #cmdevio2015
  2. 2. 2 安達 勇一 • 2013/12 入社 • TwitterID:    @UsrNameu1 • Github:    https://github.com/UsrNameu1 • Blog:    http://dev.classmethod.jp/ author/yad •        で連載やって ます
  3. 3. Topics for today • Enum • Collection API • BrightFutures 3Ⓒ Classmethod, Inc.
  4. 4. Topics for today • Enum • Collection API • BrightFutures 4Ⓒ Classmethod, Inc.
  5. 5. Enum • 離散値とEnum • リソースとEnum • エラーとEnum 5Ⓒ Classmethod, Inc.
  6. 6. 離散値とEnum • 決まった数値のみ許容するAPIのEndpoint : 6Ⓒ Classmethod, Inc. POST api/v1/user [ { "name" : "Tarou", "gender" : 1 }, { "name" : "Yoko", "gender" : 2 } ]
  7. 7. 離散値とEnum • 決まった数値のみ許容するAPIのEndpoint : 7Ⓒ Classmethod, Inc. POST api/v1/user [ { "name" : "Tarou", "gender" : 1 }, { "name" : "Yoko", "gender" : 2 } ] 決まった数値以外は 400 Bad Request
  8. 8. 離散値とEnum • 対応するモデル 8Ⓒ Classmethod, Inc. struct User { let name: String let gender: Int }
  9. 9. 離散値とEnum • 対応するモデル 9Ⓒ Classmethod, Inc. struct User { let name: String let gender: Int } 違う、そうじゃない! struct User { let name: String let gender: Gender } enum Gender: Int { case Male = 1 case Female = 2 }
  10. 10. 離散値とEnum • 限られた値しかとらない数値はEnumにすることで… →APIエラーを防げる 10Ⓒ Classmethod, Inc. POST api/v1/user [ { "name" : "Tarou", "gender" : 1 }, { "name" : "Yoko", "gender" : 2 } ] 決まった数値以外は 400 Bad Request
  11. 11. 離散値とEnum • 限られた値しかとらない数値はEnumにすることで… 11Ⓒ Classmethod, Inc. switch user.gender { case 1 : println(“male”) case 2 : println(“female”) default : assert(false, “error”) }
  12. 12. 離散値とEnum • 限られた値しかとらない数値はEnumにすることで… →網羅性チェックによりassertionを書く手間を省ける 12Ⓒ Classmethod, Inc. switch user.gender { case .Male : println(“male”) case .Female : println(“female”) }
  13. 13. 13Ⓒ Classmethod, Inc. 離散値はEnumにして IOを型として束縛
  14. 14. Enum • 離散値とEnum • リソースとEnum • エラーとEnum 14Ⓒ Classmethod, Inc.
  15. 15. リソースとEnum • Enumで宣言された値に対する • NSLocalizedString • UIImage →Objective-Cではコンバータやカテゴリ拡張を  別に実装するなどで対処。 15Ⓒ Classmethod, Inc.
  16. 16. リソースとEnum • Enumで宣言された値に対する • NSLocalizedString • UIImage →SwiftではEnumに直接書けるようになりました! 16Ⓒ Classmethod, Inc.
  17. 17. リソースとEnum • NSLocalizedStringを性別に対して取得 17Ⓒ Classmethod, Inc. enum Gender: Int { case Male = 1 case Female = 2 } extension Gender { var localizedString: String { switch self { case .Male: return NSLocalizedString(“male”, comment: “”) case .Female: return NSLocalizedString(“female”, comment: “”) } } }
  18. 18. リソースとEnum • UIImageを性別に対して取得 18Ⓒ Classmethod, Inc. enum Gender: Int { case Male = 1 case Female = 2 } extension Gender { var thumbImage: UIImage { switch self { case .Male: return UIImage(named: “male”) case .Female: return UIImage(named: “female”) } } }
  19. 19. リソースとEnum • Before • After 19Ⓒ Classmethod, Inc. cell.thumbImage = [UIImage thumbImageWithGender: gender]; cell.title = [NSString localizedStringWithGender: gender]; cell.thumbImage = gender.thumbImage cell.title = gender.localizedString
  20. 20. 20Ⓒ Classmethod, Inc. Enumに紐付くリソースは 自身で管理・記述を簡潔化
  21. 21. Enum • 離散値とEnum • リソースとEnum • エラーとEnum 21Ⓒ Classmethod, Inc.
  22. 22. エラーとEnum • Objective-Cでの典型的なエラーハンドリング (ライトバック渡し) 22Ⓒ Classmethod, Inc. NSError *error = nil; NSData *aData = [NSData dataWithContentsOfURL:pathURL options:NSDataReadingUncached error:&error]; if (!error) { // エラーがない時の処理 } else { // エラーがある時の処理 }
  23. 23. エラーとEnum • エラーハンドリングについてはほぼ定形の処理 • エラーが無い時に続けて簡単に処理を書きたい… • Optionalでは何のエラーかわからない… 23Ⓒ Classmethod, Inc.
  24. 24. エラーとEnum 24Ⓒ Classmethod, Inc. • エラーハンドリングについてはほぼ定形の処理 • エラーが無い時に続けて簡単に処理を書きたい… • Optionalでは何のエラーかわからない… そのお悩み Result<T>が 解決します!!!!
  25. 25. エラーとEnum • Result<T> 25Ⓒ Classmethod, Inc. public enum Result<T> { case Success(Box<T>) case Failure(NSError) public init(_ value: T) { self = .Success(Box(value)) } } public final class Box<T> { public let value: T public init(_ value: T) { self.value = value } } エラーの可能性 を持った値 コンパイラによるエラー 回避の為のBoxクラス
  26. 26. エラーとEnum • Before • After 26Ⓒ Classmethod, Inc. - (NSData *)dataWithURL:(NSURL *)filePathURL error:(NSError *)error { // エラーがあるときにはerrorにポインタを渡し // エラーがない時にnilでないNSData*を返す。 } func dataWithURL(url: NSURL) -> Result<NSData> { // エラーがあるときもない時もResult型を返す。 }
  27. 27. エラーとEnum • map in Optional<T> 27Ⓒ Classmethod, Inc. // Noneの可能性をもった値を let someInt = “127”.toInt() // Noneの可能性を保ったまま中身だけ変更 someInt.map { val in val + 1 }
  28. 28. エラーとEnum • map in Optional<T> 28Ⓒ Classmethod, Inc. Some None Optional<T> Optional<U> map(f: T -> U) T None U None f
  29. 29. エラーとEnum • map in Result<T> 29Ⓒ Classmethod, Inc. extension Result { func map<U>(f: T -> U) -> Result<U> { switch self { case .Success(let box) : return .Success(Box(f(box.value))) case .Failure(let err) : return .Failure(err) } } } エラーの可能性を保って中の値をマッピングする
  30. 30. エラーとEnum • map in Result<T> 30Ⓒ Classmethod, Inc. // NSErrorの可能性をもった値を let someInt = Result(127) // NSErrorの可能性を保ったまま中身だけ変更 someInt.map { val in val + 1 } エラーの可能性を保って中の値をマッピングする
  31. 31. エラーとEnum 31Ⓒ Classmethod, Inc. Success Failure Result<T> Result<U> map(f: T -> U) T NSError U NSError f • map in Result<T>
  32. 32. エラーとEnum • flatMap in Optional<T> (Swift 1.2) 32Ⓒ Classmethod, Inc. // Noneの可能性をもった値を let someStr: String? = “127” // 中身があったら新しい // Noneの可能性をもった値に変更 let someInt = someStr?.toInt() Optional Chaining
  33. 33. エラーとEnum • flatMap in Optional<T> (Swift 1.2) 33Ⓒ Classmethod, Inc. // Noneの可能性をもった値を let someInt = “127”.toInt() // 中身があったら新しい // Noneの可能性をもった値に変更する someInt.flatMap { val as? UInt8 } // Noneの可能性をもった値を let someStr: String? = “127” // 中身があったら新しい // Noneの可能性をもった値に変更 let someInt = someStr.flatMap { str in str.toInt() }
  34. 34. エラーとEnum • flatMap in Optional<T> (Swift 1.2) 34Ⓒ Classmethod, Inc. // Noneの可能性をもった値を let someInt = “127”.toInt() // 中身があったら新しい // Noneの可能性をもった値に変更する someInt.flatMap { val as? UInt8 } // Noneの可能性をもった値を let someStr: String? = “127” // 中身があったら新しい // Noneの可能性をもった値に変更 let someInt = someStr.flatMap(String.toInt) 無引数インスタンスメソッドを関数として扱う
  35. 35. エラーとEnum 35Ⓒ Classmethod, Inc. Some None Optional<T> T None f flatMap(f: T -> Optional<U>) Optional<U> U None • flatMap in Optional<T> (Swift 1.2)
  36. 36. エラーとEnum 36Ⓒ Classmethod, Inc. extension Result { func flatMap<U>(f: T -> Result<U>) -> Result<U> { switch self { case .Success(let box) : return f(box.value) case .Failure(let err) : return .Failure(err) } } } 新しいエラー可能性を持つ値にマッピングしてマージ • flatMap in Result<T>
  37. 37. エラーとEnum • flatMap in Result<T> 37Ⓒ Classmethod, Inc. // NSErrorの可能性をもった値を let someInt = Result(127) // 中身があったら新しい // 新しいNSErrorの可能性をもった値に変更 someInt.flatMap{ val in Result(val + 1)} 新しいエラー可能性を持つ値にマッピングしてマージ
  38. 38. エラーとEnum 38Ⓒ Classmethod, Inc. Success Failure Result<T> T NSError f flatMap(f: T -> Result<U>) Result<U> U NSError • flatMap in Result<T>
  39. 39. 39Ⓒ Classmethod, Inc. Enumでエラーの 可能性を持つ 値を作る
  40. 40. 40Ⓒ Classmethod, Inc.
  41. 41. Topics for today • Enum • Collection API • BrightFutures 41Ⓒ Classmethod, Inc.
  42. 42. Collection API • 実践 CollectionAPI • map, filter, reduce • flatMap(Swift 1.2) 42Ⓒ Classmethod, Inc.
  43. 43. let names = users.map { user in user.name } println(names) 実践 CollectionAPI • Swiftのコードでfor文は一回も使わなかった 43Ⓒ Classmethod, Inc. var names = [String]() for user in users { names.append(user.name) } println(names) マッピングのたびに コード領域に変数が 一つ加わる 変数という状態を 考えずに済む
  44. 44. let totalAge = users.reduce(0) { total, user in total + user.age } println(totalAge) 実践 CollectionAPI • Swiftのコードでfor文は一回も使わなかった 44Ⓒ Classmethod, Inc. var totalAge = 0 for user in users { totalAge += user.age } println(totalAge) 集計の際に変数1つが コード領域に加わる 集計の際に変数は 考えなくていい
  45. 45. 実践 CollectionAPI • コード量を大幅に削減できた 45Ⓒ Classmethod, Inc. - (NSArray *)namesForUsers:(NSArray *)users { NSMutableArray *names = [NSMutableArray new]; for(User *user in users) { [names addObject:user.name]; } return [NSArray arrayWithArray:names]; } のようなマッピング用のメソッド、処理がmap一つで書ける
  46. 46. 実践 CollectionAPI • メモリ管理のためにunownedやweakを使う 46Ⓒ Classmethod, Inc. users.map { [weak self] user in self?.names.append(user.name) return Void() } • map等のクロージャでselfを使う場合は  循環参照の可能性からweak, unownedを考慮する • 設計を考え直す
  47. 47. 47Ⓒ Classmethod, Inc. 関数フローを用い コード領域から できるだけ状態を排する
  48. 48. Collection API • 実践 CollectionAPI • map, filter, reduce • flatMap(Swift 1.2) 48Ⓒ Classmethod, Inc.
  49. 49. map, filter, reduce • map 49Ⓒ Classmethod, Inc. Array<T> Array<U> map(transform: T -> U) T U T T U U transform
  50. 50. map, filter, reduce • filter 50Ⓒ Classmethod, Inc. Array<T> Array<T> filter(includeElement: T -> Bool) T T T true/false T T includeElement
  51. 51. map, filter, reduce • reduce 51Ⓒ Classmethod, Inc. Array<T> reduce(initial: U, combine: (U, T) -> U) T combine T T U U initial
  52. 52. map, filter, reduce • 文字列の配列のうち、二文字以上のものを選び、  文字数のトータルを集計する 52Ⓒ Classmethod, Inc. Before NSArray *strings = [@“aaaa”, @“bbb”, @“c”, @“dd”]; NSUInteger totalLengthForStrings = 0; for(NSString *string in strings) { NSUInteger lengthOfString = string.length if (lengthOfString >= 2) { totalLengthForStrings += lengthOfString } } NSLog(@“%ld”, totalLengthForStrings) // 9
  53. 53. map, filter, reduce • 文字列の配列のうち、二文字以上のものを選び、  文字数のトータルを集計する 53Ⓒ Classmethod, Inc. After let strings = [“aaaa”, “bbb”, “c”, “dd”] let totalCount = strings.map(countElements) .filter { count in count >= 2 } .reduce(0, +) println(totalCount) // 9
  54. 54. 54Ⓒ Classmethod, Inc. コレクションを 関数フローで 整形・選択・集計する
  55. 55. Collection API • 実践 CollectionAPI • map, filter, reduce, sorted, first, last • flatMap(Swift 1.2) 55Ⓒ Classmethod, Inc.
  56. 56. 56Ⓒ Classmethod, Inc. flatMap(Swift 1.2) let strings = [“aaaa”, “bbb”] let bothCaseStrings = strings.flatMap { str in [str.uppercaseString, str.lowercaseString] } println(bothCaseStrings) // [“aaaa”, “AAAA”, “bbb”, “BBB”]
  57. 57. 57Ⓒ Classmethod, Inc. flatMap(Swift 1.2) Array<T> Array<U> flatMap(transform: T -> [U]) T U transform T T U U U U U
  58. 58. 58Ⓒ Classmethod, Inc.
  59. 59. Topics for today • Enum • Collection API • BrightFutures 59Ⓒ Classmethod, Inc.
  60. 60. BrightFuture • Futures in Swift • Future • Promise • メソッド概観 • Pluggable Activities 60Ⓒ Classmethod, Inc.
  61. 61. • Swiftz https://github.com/typelift/swiftz • BrightFutures https://github.com/Thomvis/BrightFutures 61Ⓒ Classmethod, Inc. Futures in Swift
  62. 62. • Swiftz 関数型プログラミングインターフェイスをSwiftに追加 62Ⓒ Classmethod, Inc. Futures in Swift
  63. 63. • Swiftz 多くの演算子はHaskellやF#から由来している 中には • (Option+8) などの特殊文字もある 63Ⓒ Classmethod, Inc. Futures in Swift
  64. 64. • Swiftz 非同期を扱う為のクラスFutureも 抽象度の高い基底クラスを有するため採用見送り 64Ⓒ Classmethod, Inc. Futures in Swift
  65. 65. • Swiftz 非同期を扱う為のクラスFutureも 抽象度の高い基底クラスを有するため採用見送り 65Ⓒ Classmethod, Inc. Futures in Swift
  66. 66. 66Ⓒ Classmethod, Inc. BrightFutures
  67. 67. BrightFuture • Futures in Swift • Future • Promise • メソッド概観 • Pluggable Activities 67Ⓒ Classmethod, Inc.
  68. 68. 68 コールバックハンドラでの 非同期処理
  69. 69. 69Ⓒ Classmethod, Inc. Future • Objective-Cでの典型的な非同期ハンドリング [[SomeTaskManager sharedInstance] taskWithCompletion:^(NSData *data, NSError *err) { if (err) { // エラーハンドリング } else { // エラーがない時の処理 } }];
  70. 70. 70Ⓒ Classmethod, Inc. Future • エラーハンドリングについてはほぼ定形の処理 • エラーが無い時に続けて簡単に処理を書きたい… • 非同期処理がまたがる度にネストが深くなっていく
  71. 71. 71Ⓒ Classmethod, Inc. Future • エラーハンドリングについてはほぼ定形の処理 • エラーが無い時に続けて簡単に処理を書きたい… • 非同期処理がまたがる度にネストが深くなっていく そのお悩み Future<T>が 解決します!!!!
  72. 72. 72Ⓒ Classmethod, Inc. public class Future<T> { var result: Result<T>? = nil ... } 非同期処理エラーの可能性 を持った値 Future public enum Result<T> { case Success(Box<T>) case Failure(NSError) } エラーの可能性 を持った値 Result<T>は実装に入っている
  73. 73. 73Ⓒ Classmethod, Inc. Future Success Failure T NSError Pending None Some(Result<T>) • Futureの取りうる状態は3つ 非同期処理中 非同期処理完了
  74. 74. 74Ⓒ Classmethod, Inc. Future • Futureをつくる public func future<T>( context c: ExecutionContext = Queue.global, task: () -> T ) -> Future<T> let futureValue = future { // 何か重い処理 return 返り値 } 必要に応じてキューを指定する (Queueはdispatch_queue_tのラッパー)
  75. 75. 75 Futureは非同期エラーの 可能性をもった値
  76. 76. BrightFuture • Futures in Swift • Future • Promise • メソッド概観 • Pluggable Activities 76Ⓒ Classmethod, Inc.
  77. 77. 77Ⓒ Classmethod, Inc. Promise • Future<T>の生成に利用 func someTask() -> Future<NSData> { let promise = Promise<NSData>() SomeTaskManager.sharedInstance .taskWithCompletion { data, err in if err != nil { // エラーハンドリング promise.failure(err) } else { // エラーがない時の処理 promise.success(data) } } return promise.future }
  78. 78. 78Ⓒ Classmethod, Inc. Promise • 「約束」「契約」を表すオブジェクト func someTask() -> Future<NSData> { let promise = Promise<NSData>() SomeTaskManager.sharedInstance .taskWithCompletion { data, err in if err != nil { // エラーハンドリング promise.failure(err) } else { // エラーがない時の処理 promise.success(data) } } return promise.future } コールバックが一回きり呼ばれる 契約を表す Futureをエラーで 完了させる Futureを成功で 完了させる
  79. 79. 79Ⓒ Classmethod, Inc. Promise • 非同期処理が呼ばれた証として  Future<T>オブジェクトを発行 func someTask() -> Future<NSData> { let promise = Promise<NSData>() SomeTaskManager.sharedInstance .taskWithCompletion { data, err in if err != nil { // エラーハンドリング promise.failure(err) } else { // エラーがない時の処理 promise.success(data) } } return promise.future } Futureを発行する
  80. 80. 80Ⓒ Classmethod, Inc. BoltsFramework Promise
  81. 81. 81Ⓒ Classmethod, Inc. • BrightFutures と BoltsFrameworkの比較 - (BFTask *)someTask { BFTaskCompletionSource *task = [BFTaskCompletionSource taskCompletionSource]; [[SomeTaskManager sharedInstance] taskWithCompletion:^(NSData *data, NSError *err) { if (err) { [task setError:err]; } else { [task setResult:data]; } }]; return task.task; } Promise Sourseの生成 完了処理 BFTaskをSourceから生成
  82. 82. 82Ⓒ Classmethod, Inc. • BrightFutures と BoltsFrameworkの比較 func someTask() -> Future<NSData> { let promise = Promise<NSData>() SomeTaskManager.sharedInstance() .taskWithCompletion { data, err in if err != nil { promise.failure(err) } else { promise.success(data) } } return promise.future } Promise Promiseの生成 完了処理 FutureをPromiseから生成
  83. 83. 83Ⓒ Classmethod, Inc. Promise • Promiseは発行したら必ず成功かエラーを一回だけ 発行するように実装 • Promiseに複数の成功を送るとランタイムエラーを 起こす • 複数回呼ばれるようなDelegateとは相性が悪い
  84. 84. 84 コールバックハンドラには Promiseを用いてFutureを生成
  85. 85. BrightFuture • Futures in Swift • Future • Promise • メソッド概観 • Pluggable Activities 85Ⓒ Classmethod, Inc.
  86. 86. 86Ⓒ Classmethod, Inc. メソッド概観 • onComplete in Future<T> onComplete( callback: Result<T> -> Void ) -> Future<T> T NSError None Result<T> callback Future<T>
  87. 87. 87Ⓒ Classmethod, Inc. メソッド概観 futureTask.onComplete { result in switch result { case .Success(let val): () case .Failure(let err): () } } 非同期計算の結果にかかわらす Result<T> を返却 • onComplete in Future<T>
  88. 88. 88Ⓒ Classmethod, Inc. メソッド概観 • onSuccess in Future<T> onSuccess( callback: T -> Void ) -> Future<T> T NSError None Result<T> callback Future<T>
  89. 89. 89Ⓒ Classmethod, Inc. メソッド概観 • onSuccess in Future<T> futureTask.onSuccess { value in // T型のvalueに対する処理 } 非同期計算が成功した場合 Tを返却
  90. 90. 90Ⓒ Classmethod, Inc. メソッド概観 • onFailure in Future<T> onFailure( callback: NSError -> Void ) -> Future<T> T NSError None Result<T> Future<T> callback
  91. 91. 91Ⓒ Classmethod, Inc. メソッド概観 futureTask.onFailure { error in // NSError型のerrorに対する処理 } 非同期計算が成功した場合 NSError を返却 • onFailure in Future<T>
  92. 92. 92Ⓒ Classmethod, Inc. メソッド概観 • map in Future<T> Future<T> Future<U> map(f: T -> U) T NSError U NSError f None
  93. 93. 93Ⓒ Classmethod, Inc. // 非同期エラーの可能性をもった値を let futureData = someTask() // Future<NSData>型の返り値 // 非同期エラーの可能性を保ったまま中身だけ変更 futureData.map { data in NSString( data: data, encoding: NSUTF8StringEncoding ) } // Future<NSString>型の返り値 メソッド概観 • map in Future<T>
  94. 94. 94Ⓒ Classmethod, Inc. メソッド概観 • flatMap in Future<T> Future<T> Future<U> flatMap(f: T -> Future<U>) T NSError U NSError f None
  95. 95. 95Ⓒ Classmethod, Inc. // 非同期エラーの可能性をもった値を let someURLString = someURLTask()// Future<String>型の返り値 // 中身がエラーでなければ続きの // 非同期エラー可能性をもった値を評価 someURLString.flatMap(fetchData) // fetchData: Stringを引数にもち // Future<NSData>を返り値に持つ関数 メソッド概観 • flatMap in Future<T>
  96. 96. 96 非同期処理を定形的な ハンドリングで記述
  97. 97. BrightFuture • Futures in Swift • Future • Promise • メソッド概観 • Pluggable Activities 97Ⓒ Classmethod, Inc.
  98. 98. • 非同期処理のまとまり毎にFutureを生成 98Ⓒ Classmethod, Inc. Pluggable Activities →非同期処理同士を抜き差し、順序入替しやすくなった Web API Task App DB Task Web API TaskApp DB Task
  99. 99. • 非同期処理のまとまり毎にFutureを生成 99Ⓒ Classmethod, Inc. Pluggable Activities Web API App DB HeavyTaskInfrastructure Use case Authentication UserLogic →ロジックが   非同期を要する処理かどうかがわかりやすくなった
  100. 100. →アクティビティ図とコードが対応するようになった 100Ⓒ Classmethod, Inc. Pluggable Activities User Event API Call DB Update NSError NSError Success • 非同期処理のまとまり毎にFutureを生成
  101. 101. 101 Futureでアカルイ 非同期処理
  102. 102. 102Ⓒ Classmethod, Inc.
  103. 103. 103 おまけ
  104. 104. Topics for today • Enum • Collection API • BrightFutures 104Ⓒ Classmethod, Inc.
  105. 105. Topics for today • Enum • Collection API • BrightFutures 105Ⓒ Classmethod, Inc. Optional<T> Result<T> Array<T> Future<T>
  106. 106. 106
  107. 107. • Enum • Collection API • BrightFutures 107Ⓒ Classmethod, Inc. Optional<T> Result<T> Array<T> Future<T> map map(f: T -> U) -> U? map(f: T -> U) -> Result<U> map(f: T -> U) -> Array<U> map(f: T -> U) -> Future<U>
  108. 108. • Enum • Collection API • BrightFutures 108Ⓒ Classmethod, Inc. flatMap Optional<T> Result<T> Array<T> Future<T> flatMap(f: T -> U?) -> U? flatMap(f: T -> Result<U>) -> Result<U> flatMap(f: T -> Array<U>) -> Array<U> flatMap(f: T -> Future<U>) -> Future<U>
  109. 109. 109Ⓒ Classmethod, Inc. map ・ flatMapを 適用できる型を抽象化 XXX<T> map(f: T -> U) -> XXX<U> flatMap(f: T -> XXX<U>) -> XXX<U> Functor・Applicative・Monadへ
  110. 110. 110
  111. 111. 111Ⓒ Classmethod, Inc. Haskell・Scala等の 先達に根拠を求める
  112. 112. 112Ⓒ Classmethod, Inc. 巨人の肩に乗る
  113. 113. Developer Day スライドは後日ブログで公開します。 113 A-1 Ⓒ Classmethod, Inc. #cmdevio2015

×