Skip to content

Instantly share code, notes, and snippets.

@iThinker
Last active February 28, 2017 19:28
Show Gist options
  • Save iThinker/7d44478496422e96a661cdce2a1ec4b2 to your computer and use it in GitHub Desktop.
Save iThinker/7d44478496422e96a661cdce2a1ec4b2 to your computer and use it in GitHub Desktop.
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
func async<T>(_ executable: @escaping @autoclosure () -> T, _ priority: DispatchQoS.QoSClass = DispatchQoS.QoSClass.default, completion: @escaping (T) -> Void) {
DispatchQueue.global(qos: priority).async {
let result = executable()
DispatchQueue.main.async {
completion(result)
}
}
}
func asyncWithError<T>(_ executable: @escaping @autoclosure () throws -> T, _ priority: DispatchQoS.QoSClass = DispatchQoS.QoSClass.default, completion: @escaping (T?, Error?) -> Void) {
DispatchQueue.global(qos: priority).async {
var result: T? = nil
var error: Error? = nil
do {
result = try executable()
}
catch let caughtError {
error = caughtError
}
DispatchQueue.main.async {
completion(result, error)
}
}
}
infix operator =>
func =><T>(left: @escaping @autoclosure () -> T, right: @escaping (T) -> Void) {
async(left, completion: right)
}
infix operator =>>
func =>><T>(left: @escaping @autoclosure () throws -> T, right: @escaping (T?, Error?) -> Void) {
asyncWithError(left, completion: right)
}
func toAsync<U, T>(_ executable: @escaping (U) -> T) -> ((U, @escaping ((T) -> Void)) -> Void) {
return {
input, completion in
async(executable(input), completion: completion)
}
}
func toAsyncWithError<U, T>(_ executable: @escaping (U) throws -> T) -> ((U, @escaping ((T?, Error?) -> Void)) -> Void) {
return {
input, completion in
do {
asyncWithError(try executable(input), completion: completion)
}
catch {}
}
}
class TestExecutor {
func perform(_ input: String) -> String {
return input + " Performed"
}
enum Error: String, Swift.Error, LocalizedError {
case Empty
var errorDescription: String? {
return self.rawValue
}
}
func throwingPerform(_ input: String) throws -> String {
if input.isEmpty {
throw Error.Empty
}
return self.perform(input)
}
func multiplePerform(_ input: String, secondArg: Int) -> String {
return input + " " + String(secondArg) + " Multiple Args Performed"
}
func multipleThrowingPerform(_ input: String, secondArg: Int) throws -> String {
if input.isEmpty || secondArg == 0 {
throw Error.Empty
}
return self.multiplePerform(input, secondArg: secondArg)
}
}
let executor = TestExecutor()
let syncResult = executor.perform("Hi")
let group = DispatchGroup()
group.enter()
executor.perform("Operator") => { result in
print(result)
group.leave()
}
group.enter()
executor.perform("Wut") =>> { result, error in
print("result: ", result ?? "no result", ", error: ", error?.localizedDescription ?? "no error")
group.leave()
}
group.enter()
try executor.throwingPerform("") =>> { result, error in
print("result: ", result ?? "no result", ", error: ", error?.localizedDescription ?? "no error")
group.leave()
}
group.enter()
async(executor.perform("Async")) { result in
print(result)
group.leave()
}
group.enter()
asyncWithError(try executor.throwingPerform("")) { result, error in
print("result: ", result ?? "no result", ", error: ", error?.localizedDescription ?? "no error")
group.leave()
}
func finishAsync<T>(_ result: T) {
print(result)
group.leave()
}
group.enter()
executor.perform("Finish Function") => finishAsync
let asyncPerform = toAsync(executor.multiplePerform)
group.enter()
asyncPerform(("Asynced Function", 5)) { result in
print(result)
group.leave()
}
let asyncPerformWithError = toAsyncWithError(executor.multipleThrowingPerform)
group.enter()
asyncPerformWithError(("", 0)) { result, error in
print("result: ", result ?? "no result", ", error: ", error?.localizedDescription ?? "no error")
group.leave()
}
group.notify(queue: .main) {
PlaygroundPage.current.finishExecution()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment