Skip to content

Instantly share code, notes, and snippets.

@vinivendra
Last active April 12, 2018 14:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vinivendra/d3a308e83acdc100133a to your computer and use it in GitHub Desktop.
Save vinivendra/d3a308e83acdc100133a to your computer and use it in GitHub Desktop.
import Foundation
// Usage examples at the end of the gist
func giveEmotionsToFunction<InputType, OutputType>
(_ function: @escaping (InputType) -> OutputType) -> ((InputType) -> OutputType)
{
return { input in
print(" =) ")
let output = function(input)
print(" =( ")
return output
}
}
func createPerformanceLogDelegate<InputType, OutputType>(
_ functionName: String = "",
_ function: @escaping ((InputType) -> OutputType)) -> ((InputType) -> OutputType)
{
return { argument in
let start = DispatchTime.now()
let result = function(argument)
let end = DispatchTime.now()
let nanoTime = end.uptimeNanoseconds - start.uptimeNanoseconds
let timeInterval = Double(nanoTime) / 1_000_000_000 // Could overflow
print("\(functionName)(\(argument)) = \(result)\n\(timeInterval) seconds to evaluate.")
return result
}
}
func createLogDelegate<InputType, OutputType>(
_ functionName: String = "",
_ function: @escaping ((InputType) -> OutputType)) -> ((InputType) -> OutputType)
{
return { argument in
let result = function(argument)
print("\(functionName)(\(argument)) = \(result)")
return result
}
}
func createRecursiveLogDelegate<InputType, OutputType>(
_ functionName: String = "",
_ function: @escaping ((((InputType) -> OutputType), InputType) -> OutputType))
-> ((InputType) -> OutputType)
{
var delegateFunction: ((InputType) -> OutputType)!
var indentation = -1
delegateFunction = { argument in
indentation += 1
let result = function(delegateFunction, argument)
for _ in 0..<indentation {
print(" ", terminator:"")
}
print("\(functionName)(\(argument)) = \(result)")
indentation -= 1
return result
}
return delegateFunction
}
func fibonacci(_ recursive: ((Int) -> Int), n: Int) -> Int {
if n <= 2 {
return 1
} else {
return recursive(n - 1) + recursive(n - 2)
}
}
func createMemoizeDelegate<InputType: Hashable, OutputType>(
_ function: @escaping ((((InputType) -> OutputType), InputType) -> OutputType))
-> ((InputType) -> OutputType)
{
var table = [InputType : OutputType]()
var delegateFunction: ((InputType) -> OutputType)!
delegateFunction = { argument in
if let result = table[argument] {
return result
} else {
let result = function(delegateFunction, argument)
table[argument] = result
return result
}
}
return delegateFunction
}
func factorial(_ n: Int) -> Int {
return n <= 1 ? 1 : factorial(n-1) * n
}
func createTestDelegate<InputType, OutputType: Equatable>(
_ function: @escaping (InputType) -> OutputType) -> ((InputType, OutputType) -> ())
{
return { input, output in
assert(function(input) == output)
}
}
func createAsyncDelegate<InputType, OutputType>(
queue: qos_class_t = QOS_CLASS_BACKGROUND,
callback: @escaping (OutputType) -> () = { _ in },
function: @escaping ((InputType) -> OutputType)) -> ((InputType) -> ())
{
return { argument in
DispatchQueue.global(qos: .userInitiated).async {
let result = function(argument)
DispatchQueue.main.async {
callback(result)
}
}
}
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// Examples
/////////////////////////////////////////////////////////////////////////////
let importantFunction = { print("Hello!") }
let importantFunctionWithEmotions: () -> () = {
print(" =) ")
importantFunction()
print(" =( ")
}
importantFunctionWithEmotions() // Smiles, does its work, then frowns
print()
/////////////////////////////////////////////////////////////////////////////
let foo = { print($0) }
let fooWithEmotions = giveEmotionsToFunction(foo)
fooWithEmotions("Hello!")
print()
/////////////////////////////////////////////////////////////////////////////
func addOne(_ n: Int) -> Int {
return n + 1
}
let addOneAndLog = createPerformanceLogDelegate("addOne", addOne)
let three = addOneAndLog(2)
// Prints:
// addOne(2) = 3
// 2.57e-07 seconds to evaluate.
print()
/////////////////////////////////////////////////////////////////////////////
let logFibonacci = createRecursiveLogDelegate("fibonacci", fibonacci)
let hundredAndTwenty = logFibonacci(5)
// Prints:
// fibonacci(2) = 1
// fibonacci(1) = 1
// fibonacci(3) = 2
// fibonacci(2) = 1
// fibonacci(4) = 3
// fibonacci(2) = 1
// fibonacci(1) = 1
// fibonacci(3) = 2
//fibonacci(5) = 5
print()
/////////////////////////////////////////////////////////////////////////////
let memoizedFibonacci = createMemoizeDelegate(fibonacci)
let bigNumber = memoizedFibonacci(50) // Runs in O(n) instead of O(holy crap!)
// or O(1) if called in order
print(bigNumber)
// This probably won't return before the program ends so we won't see the result :(
let asyncFactorial = createAsyncDelegate(
callback: { print("Async factorial returned! Result is \($0)") },
function: factorial)
// Calculates in a separate thread, prints the result in the main thread
asyncFactorial(20)
print()
/////////////////////////////////////////////////////////////////////////////
let testFactorial = createTestDelegate(factorial)
// Tests each input against its expected output
testFactorial(1, 1)
testFactorial(2, 2)
testFactorial(3, 6)
testFactorial(4, 24)
testFactorial(5, 120)
/////////////////////////////////////////////////////////////////////////////
let logFib = createLogDelegate("f", fibonacci)
let allFibonacci = createMemoizeDelegate(logFib)
_ = allFibonacci(40) // Prints every fibonacci number from 1 to 40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment