8.
離散値とEnum
• 対応するモデル
8Ⓒ Classmethod, Inc.
struct User {
let name: String
let gender: Int
}
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
}
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.
エラーとEnum
• Before
• After
26Ⓒ Classmethod, Inc.
- (NSData *)dataWithURL:(NSURL *)filePathURL
error:(NSError *)error
{
// エラーがあるときにはerrorにポインタを渡し
// エラーがない時にnilでないNSData*を返す。
}
func dataWithURL(url: NSURL) -> Result<NSData>
{
// エラーがあるときもない時もResult型を返す。
}
27.
エラーとEnum
• map in Optional<T>
27Ⓒ Classmethod, Inc.
// Noneの可能性をもった値を
let someInt = “127”.toInt()
// Noneの可能性を保ったまま中身だけ変更
someInt.map { val in val + 1 }
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.
エラーと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.
エラーとEnum
• map in Result<T>
30Ⓒ Classmethod, Inc.
// NSErrorの可能性をもった値を
let someInt = Result(127)
// NSErrorの可能性を保ったまま中身だけ変更
someInt.map { val in val + 1 }
エラーの可能性を保って中の値をマッピングする
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.
エラーとEnum
• flatMap in Optional<T> (Swift 1.2)
32Ⓒ Classmethod, Inc.
// Noneの可能性をもった値を
let someStr: String? = “127”
// 中身があったら新しい
// Noneの可能性をもった値に変更
let someInt = someStr?.toInt()
Optional Chaining
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.
エラーと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.
エラーと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.
エラーと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.
エラーとEnum
• flatMap in Result<T>
37Ⓒ Classmethod, Inc.
// NSErrorの可能性をもった値を
let someInt = Result(127)
// 中身があったら新しい
// 新しいNSErrorの可能性をもった値に変更
someInt.flatMap{ val in Result(val + 1)}
新しいエラー可能性を持つ値にマッピングしてマージ
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>
41.
Topics for today
• Enum
• Collection API
• BrightFutures
41Ⓒ Classmethod, Inc.
42.
Collection API
• 実践 CollectionAPI
• map, filter, reduce
• flatMap(Swift 1.2)
42Ⓒ Classmethod, Inc.
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.
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つが
コード領域に加わる
集計の際に変数は
考えなくていい
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Ⓒ Classmethod, Inc.
Future
Success
Failure
T
NSError
Pending None
Some(Result<T>)
• Futureの取りうる状態は3つ
非同期処理中
非同期処理完了
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のラッパー)
85.
BrightFuture
• Futures in Swift
• Future
• Promise
• メソッド概観
• Pluggable Activities
85Ⓒ Classmethod, Inc.
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Ⓒ Classmethod, Inc.
メソッド概観
futureTask.onComplete { result in
switch result {
case .Success(let val): ()
case .Failure(let err): ()
}
}
非同期計算の結果にかかわらす
Result<T> を返却
• onComplete in Future<T>
88.
88Ⓒ Classmethod, Inc.
メソッド概観
• onSuccess in Future<T>
onSuccess(
callback: T -> Void
) -> Future<T>
T
NSError
None
Result<T>
callback
Future<T>
89.
89Ⓒ Classmethod, Inc.
メソッド概観
• onSuccess in Future<T>
futureTask.onSuccess { value in
// T型のvalueに対する処理
}
非同期計算が成功した場合
Tを返却
90.
90Ⓒ Classmethod, Inc.
メソッド概観
• onFailure in Future<T>
onFailure(
callback: NSError -> Void
) -> Future<T>
T
NSError
None
Result<T>
Future<T>
callback
91.
91Ⓒ Classmethod, Inc.
メソッド概観
futureTask.onFailure { error in
// NSError型のerrorに対する処理
}
非同期計算が成功した場合
NSError を返却
• onFailure in Future<T>
92.
92Ⓒ Classmethod, Inc.
メソッド概観
• map in Future<T>
Future<T> Future<U>
map(f: T -> U)
T
NSError
U
NSError
f
None
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Ⓒ Classmethod, Inc.
メソッド概観
• flatMap in Future<T>
Future<T> Future<U>
flatMap(f: T -> Future<U>)
T
NSError
U
NSError
f
None
95.
95Ⓒ Classmethod, Inc.
// 非同期エラーの可能性をもった値を
let someURLString =
someURLTask()// Future<String>型の返り値
// 中身がエラーでなければ続きの
// 非同期エラー可能性をもった値を評価
someURLString.flatMap(fetchData)
// fetchData: Stringを引数にもち
// Future<NSData>を返り値に持つ関数
メソッド概観
• flatMap in Future<T>
97.
BrightFuture
• Futures in Swift
• Future
• Promise
• メソッド概観
• Pluggable Activities
97Ⓒ Classmethod, Inc.
98.
• 非同期処理のまとまり毎にFutureを生成
98Ⓒ Classmethod, Inc.
Pluggable Activities
→非同期処理同士を抜き差し、順序入替しやすくなった
Web API Task App DB Task
Web API TaskApp DB Task
99.
• 非同期処理のまとまり毎にFutureを生成
99Ⓒ Classmethod, Inc.
Pluggable Activities
Web API App DB HeavyTaskInfrastructure
Use case Authentication UserLogic
→ロジックが
非同期を要する処理かどうかがわかりやすくなった
100.
→アクティビティ図とコードが対応するようになった
100Ⓒ Classmethod, Inc.
Pluggable Activities
User Event
API Call
DB Update
NSError NSError Success
• 非同期処理のまとまり毎にFutureを生成
Be the first to comment