Kekka
已实现功能
结果
- 对可能失败的类型的抽象(上下文类型,即网络结果)
enum MathError: Error { case cannotDivideByZero } func divide(item: Int, by: Int) -> Result<Double> { if by == 0 { return .failure(error: MathError.cannotDivideByZero) } return .success(value: Double(item / by)) }
- 提供
map
和flatMap
(即bind
)/// map [Functor] divide(item: 12, by: 0).map { $0 * 2 } // still .failure(.cannotDivideByZero) divide(item: 12, by: 6).map { $0 * 2 } // .success(4) /// flatMap | bind [Monad] divide(item: 12, by: 6).flatMap { divide(item: Int($0), by: 2) } // .success(1)
未来
-
对异步任务和嵌套回调的抽象(即动画、网络、文件读取)
final class Network { public enum NetworkError: Error { case unknown } /// This is a much better way of wrapping network calls. public func get(from url: URL) -> Future<Result<Data>> { return Future { aCompletion in let session = URLSession(configuration: .default) let dataTask = session.dataTask(with: url) { (data, response, error) in if let d = data, error == nil { aCompletion?(.success(value: d)) } else if let e = error { aCompletion?(.failure(error: e)) } else { aCompletion?(.failure(error: NetworkError.unknown)) } } dataTask.resume() } } }
-
提供
map
(即then
)和flatMap
(即bind
)/// This allows one to reason code in linear way without the threading involved. let url = URL(string: "https://www.kandelvijaya.com")! Network().get(from: url).map { transformToModel($0) } // produces Future<Result<[XModel]>> .map { viewModels(from: $0) } // produces Future<Result<[XViewModel]>> .execute() /// This allows one to chain multiple future/async task into a linear way Network().get(from: url).map { extractUrls($0).first } // gets first external url .flatMap { Network().get(from: $0) } // gets data from that url .map { transformToModel($0) } // produces Future<Result<XViewModel>> .execute()
-
Result 和 Future 可以无缝工作,实现既易于推理又优雅的代码。相同的技巧可以用于链式动画、IO 和副作用编程。
待实现
IO
- 不纯计算的抽象(捕获副作用)
贡献策略
- 不追求基本的证明,而是提供语法糖和花哨的扩展
- 否则,请随意创建问题或拉取请求。