OSDN Git Service

Resultからnoneを削除
authormasakih <masakih@users.sourceforge.jp>
Wed, 17 Jan 2018 15:44:01 +0000 (00:44 +0900)
committermasakih <masakih@users.sourceforge.jp>
Wed, 17 Jan 2018 15:44:01 +0000 (00:44 +0900)
KCD/DockInformationFutures.swift
KCD/Future.swift

index 2fb05f8..2059cd7 100644 (file)
@@ -48,7 +48,7 @@ func createDockInformationFuture<T: DockInformationFutureCreatable>(number: Int)
         return future
     }
     
-    return ServerDataStore.default.future { _ -> Result<T> in
+    return ServerDataStore.default.future { _ -> Result<T>? in
         
         guard T.alreadyHasData(for: number) else { return .none }
         
index 5fa95c0..2d0eb0d 100644 (file)
@@ -8,11 +8,10 @@
 
 import Cocoa
 
-
 enum Result<T> {
     
     case value(T)
-    case none
+    
     case error(Error)
 }
 
@@ -22,7 +21,7 @@ class Future<T> {
     private let queue: DispatchQueue
     private let semaphore = DispatchSemaphore(value: 1)
     
-    private var result: Result<T> = .none
+    private var result: Result<T>?
     
     init(queue: DispatchQueue = watingQueue) {
         
@@ -30,17 +29,28 @@ class Future<T> {
         
         self.semaphore.wait()
     }
+    convenience init(queue: DispatchQueue = watingQueue, _ block: @escaping () throws -> T) {
+        
+        self.init(queue: queue)
+        
+        queue.async {
+            do {
+                self.success(try block())
+            } catch {
+                self.failure(error)
+            }
+        }
+    }
     deinit {
         semaphore.signal()
     }
     
     @discardableResult
-    func onSuccess(block: @escaping (T) -> Void) -> Future<T> {
+    func onSuccess(_ block: @escaping (T) -> Void) -> Self {
         
         queue.async {
-            
             self.semaphore.wait()
-            if case .value(let value) = self.result { block(value) }
+            if case let .value(value)? = self.result { block(value) }
             self.semaphore.signal()
         }
         
@@ -48,45 +58,85 @@ class Future<T> {
     }
     
     @discardableResult
-    func onFailure(block: @escaping (Error) -> Void) -> Future<T> {
+    func onFailure(_ block: @escaping (Error) -> Void) -> Self {
         
         queue.async {
-            
             self.semaphore.wait()
-            if case .error(let error) = self.result { block(error) }
+            if case let .error(error)? = self.result { block(error) }
             self.semaphore.signal()
         }
         
         return self
     }
     
-    func success(_ value: T) {
+    func success(_ newValue: T) {
         
         switch result {
             
-        case .value, .error:
-            Logger.shared.log("multi call success(_:)")
-            fatalError()
-            
         case .none:
-            result = .value(value)
+            result = .value(newValue)
             semaphore.signal()
+            
+        default:
+            fatalError("multi call success(_:)")
         }
     }
     
-    func failure(_ error: Error) {
+    func failure(_ newError: Error) {
         
         switch result {
             
-        case .value, .error:
-            Logger.shared.log("multi call failure(_:)")
-            fatalError()
-            
         case .none:
-            result = .error(error)
+            result = .error(newError)
             semaphore.signal()
+            
+        default:
+            fatalError("multi call failure(_:)")
+        }
+    }
+    
+    @discardableResult
+    func await() -> Self {
+        
+        semaphore.wait()
+        semaphore.signal()
+        
+        return self
+    }
+    
+    func map<U>(_ transform: @escaping (T) throws -> U) -> Future<U> {
+        
+        return Future<U> {
+            
+            self.semaphore.wait()
+            defer { self.semaphore.signal() }
+            
+            if case let .value(value)? = self.result {
+                return try transform(value)
+            }
+            if case let .error(error)? = self.result {
+                throw error
+            }
+            
+            fatalError("Not reach")
         }
     }
+    
+    func flatMap<U>(_ transform: @escaping (T) -> Future<U>) -> Future<U> {
+        
+        let future = Future<U>()
+        
+        onSuccess {
+            transform($0)
+                .onSuccess { val in future.success(val) }
+                .onFailure { error in future.failure(error) }
+        }
+        onFailure {
+            future.failure($0)
+        }
+        
+        return future
+    }
 }
 
 
@@ -99,9 +149,9 @@ extension NotificationCenter {
     ///   - object: 監視対象
     ///   - block:
     ///     Parameters: Notification
-    ///     Returns: `Result<T>` : 成功時は `.value<T>`, エラー時は `.error<Error>`, 監視を継続するときは `.none`を返す
+    ///     Returns: `Result<T>?` : 成功時は `.value<T>`, エラー時は `.error<Error>`, 監視を継続するときは `Optional.none`を返す
     /// - Returns: Notificationによって値が設定される Future<T>
-    func future<T>(name: Notification.Name, object: Any?, block: @escaping (Notification) -> Result<T>) -> Future<T> {
+    func future<T>(name: Notification.Name, object: Any?, block: @escaping (Notification) -> Result<T>?) -> Future<T> {
         
         let future = Future<T>()
         
@@ -113,11 +163,11 @@ extension NotificationCenter {
                             
                             switch block(notification) {
                                 
-                            case .value(let val): future.success(val)
+                            case .value(let val)?: future.success(val)
                                 
-                            case .none: return
+                            case .error(let error)?: future.failure(error)
                                 
-                            case .error(let error): future.failure(error)
+                            case .none: return
                             }
                             
                             token.map(NotificationCenter.default.removeObserver)
@@ -134,9 +184,9 @@ extension CoreDataProvider {
     /// - Parameters:
     ///   - block:
     ///     Parameters: Notification (NSManagedObjectContextObjectsDidChange)
-    ///     Returns: `Result<T>` : 成功時は `.value<T>`, エラー時は `.error<Error>`, 監視を継続するときは `.none`を返す
+    ///     Returns: `Result<T>?` : 成功時は `.value<T>`, エラー時は `.error<Error>`, 監視を継続するときは `Optional.none`を返す
     /// - Returns: CoreDataの更新で値が設定される Future<T>
-    func future<T>(block: @escaping (Notification) -> Result<T>) -> Future<T> {
+    func future<T>(block: @escaping (Notification) -> Result<T>?) -> Future<T> {
         
         return NotificationCenter.default
             .future(name: .NSManagedObjectContextObjectsDidChange, object: self.context, block: block)