Skip to content

Instantly share code, notes, and snippets.

@pixelspark
Last active August 6, 2016 21:17
Show Gist options
  • Save pixelspark/751d56ed9d068f2d4e695b7e7e9482e3 to your computer and use it in GitHub Desktop.
Save pixelspark/751d56ed9d068f2d4e695b7e7e9482e3 to your computer and use it in GitHub Desktop.
/** Wrap a block so that it can be called only once. Calling the returned block twice results in a fatal error. After
the first call but before returning the result from the wrapped block, the wrapped block is dereferenced. */
public func once<P, R>(_ block: ((P) -> (R))) -> ((P) -> (R)) {
#if DEBUG
var blockReference: ((P) -> (R))? = block
let mutex = Mutex()
return {(p: P) -> (R) in
let block = mutex.locked { () -> ((P) -> (R)) in
assert(blockReference != nil, "callback called twice!")
let r = blockReference!
blockReference = nil
return r
}
return block(p)
}
#else
return block
#endif
}
// Use as follows:
func longRunningOperation(_ callback: (String) -> ()) {
callback("Hello")
callback("World") // this will fail!
}
longRunningOperation(once { result in
print(result)
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment