-
-
Save alexlee002/bf64d2cdb4cd01bf9bcd909bb7883d69 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import PlaygroundSupport | |
PlaygroundPage.current.needsIndefiniteExecution = true | |
/// define an operation success or error result | |
enum Result<T> { | |
case error(Error) | |
case success(T) | |
} | |
/// define a generator function result. | |
/// a generator can yield multiple values before returning | |
enum IteratorResult<Yield, Return> { | |
case yield(Yield) | |
case done(Return) | |
} | |
/// a generator is a function that return an IteratorResult every time its called | |
typealias Generator<Yield, Return, Next> = (Next?) -> IteratorResult<Yield, Return> | |
typealias Thunk<T> = (@escaping (Result<T>) -> Void) -> Void | |
/// run a generator step bt step until its done | |
func runner<T, V>(_ generator: Generator<Thunk<T>, Thunk<V>, T>) -> Void { | |
func run(value: T?, callback: @escaping (Result<V>) -> Void) { | |
let it = generator(value) | |
switch it { | |
case .yield(let thunk): | |
thunk() { (result: Result<T>) -> Void in | |
switch result { | |
case .error(let err): | |
callback(.error(err)) | |
case .success(let value): | |
print("yield", value) | |
return run(value: value, callback: callback) | |
} | |
} | |
case .done(let thunk): | |
thunk(callback) | |
} | |
} | |
run(value: nil) { print($0) } | |
} | |
/// example of generator that yield incremented number and returns 10 | |
func incGenerator() -> Generator<Thunk<Int>, Thunk<Int>, Int> { | |
return { (prev: Int?) in | |
let next = (prev ?? 0) + 1 | |
let thunk: Thunk<Int> = { callback in | |
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { | |
callback(Result.success(next)) | |
} | |
} | |
return next < 10 | |
? .yield(thunk) | |
: .done(thunk) | |
} | |
} | |
runner(incGenerator()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment