Skip to content

Instantly share code, notes, and snippets.

@charlieMonroe
Last active May 31, 2016 10:11
Show Gist options
  • Save charlieMonroe/655f2b5e25cc0b4ba06c0ddafa41c73b to your computer and use it in GitHub Desktop.
Save charlieMonroe/655f2b5e25cc0b4ba06c0ddafa41c73b to your computer and use it in GitHub Desktop.
/// An argument of the function.
struct Argument {
var name: String
var type: Any.Type
}
/// Variable captured by the closure.
struct CapturedVariable {
var name: String
var type: Any.Type
var value: Any
/// Possibly other stuff like weak, etc.
}
protocol Function {
/* associatedtype ReturnType? */
/// Arguments taken by the function.
var arguments: [Argument] { get }
/// If it's a closure, it contains info about the
/// variables captured by the closure. Example:
///
/// var x: CGFloat = 0.0
/// let closure = { x = 3.0 }
///
/// closure.capturedVariables[0]:
/// -name: "x"
/// -type: CGFloat.self
/// -value: CGFloat(0.0)
var capturedVariables: [CapturedVariable] { get }
/// Return type of the value.
var returnValueType: Any.Type { get } // ReturnType?
/// Will execute the function/closure with arguments.
/// Since the arguments don't need to be heterogenous,
/// it's Any. If a cast to the actual arguments required
/// by the function fails, fatalError is called.
func executeWithArguments(args: Any...) -> Any /* ReturnType */
}
///// Examples of usage:
let closure1 = { print("hello") }
closure1.arguments // Empty array
closure1.capturedVariables // Empty array
let myString = "john"
let closure2 = { (string: String) -> String in (myString + string).lowercaseString }
closure2.arguments // { name: "string", type: String.Type }
closure2.capturedVariables // { name: "myString", type: String.Type, value: "john" }
let function3 = NSArray.arrayByAddingObjectsFromArray /// (NSArray) -> ([AnyObject] -> [AnyObject])
function3.arguments // { name: "self", type: NSArray.Type }
function3.capturedVariables // Empty.
function3.returnValueType /// (([AnyObject]) -> [AnyObject]).Type
class Invocation<ReturnType> {
let function: Function
func invokeOnMainThread(args: [Any]) -> ReturnType {
let result: ReturnType! = nil
dispatch_sync(dispatch_get_main_queue(), {
// #splat was discussed in another thread.
result = self.function.executeWithArguments(#splat(args)) as! ReturnType
})
return result
}
}
func doSomethingWithArgument<T>(arg: T) {
if arg is Function {
fatalError("You can't pass functions here!")
}
}
doSomethingWithArgument(closure1) // fatalError
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment