 }
 
 struct SpeakerSupervisor {
-    func getSpeaker(_ completion: @escaping (Speaker, Error?)->Void) {
+    func getSpeaker(_ completion: @escaping (Speaker?, Error?)->Void) {
         DispatchQueue.main.async {
             completion(Speaker.init(), nil)
         }
     }
     
-    func speaker: MyFuture<Speaker, Error> {
-        return MyFuture<String, Error>.init { (promise) in
-            get
+    var speaker: MyFuture<Speaker, Error> {
+        return MyFuture<Speaker, Error>.init { (promise) in
+            self.getSpeaker { (speaker, error) in
+                if let speaker = speaker {
+                    promise(.success(speaker))
+                } else if let error = error {
+                    promise(.failure(error))
+                }
+            }
         }
     }
 }
 
-func checkifTwoNamesAreEqual(speaker1: Speaker, speaker2: Speaker) -> MyFuture {
-    
+
+let supervisor = SpeakerSupervisor.init()
+
+supervisor.getSpeaker { (speaker, error) in
+    speaker?.getName({ (name, error) in
+        print(name!)
+    })
 }
 
-func fetchUser(id: Int) -> MyFuture<Speaker, Error> {
-    return MyFuture { resolve in
-        after(0.1) {
-            resolve(.success(User(id: id, name: "M.D.")))
-        }
-    }
-}
+supervisor
+    .speaker
+    .myFlatMap { try! $0.get().getName }
+    .observe {print($0)}
 
-fetchUser(id: 5)

    }
}


struct Speaker {
    func getName(_ completion: @escaping (String?, Error?)->Void) {
        DispatchQueue.main.async {
            completion("Boom 3", nil)
        }
    }
    

import PlaygroundSupport
import Foundation

PlaygroundPage.current.needsIndefiniteExecution = true

func after(_ timeInterval: TimeInterval = 0.1, work: @escaping () -> Void) {
    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + timeInterval, execute: work)
}

//https://developer.apple.com/documentation/combine/future/3333367-init

final class MyFuture<Output, Failure> where Failure: Error {
    typealias FutureResult = Result<Output, Failure>
    typealias Promise = (FutureResult) -> Void
    
    var result: Result<Output, Failure>?
//    var attempt: (@escaping (FutureResult) -> Void) -> Void
    var callbacks: [(FutureResult) -> Void] = []
    init(_ attemptToFulfill: @escaping (@escaping (FutureResult) -> Void) -> Void) {
//        attempt = attemptToFulfill
        attemptToFulfill(resolve)
    }
    
    func observe(_ onResolved: @escaping (FutureResult) -> Void) {
//        if result == nil {
//            attempt(resolve)
//        }
        callbacks.append(onResolved)
        callCallbacks()
    }
        
    private func resolve(result: FutureResult) {
        self.result = result
        callCallbacks()
    }
    
    private func callCallbacks() {
