Created
February 12, 2017 10:39
-
-
Save ignazioc/df0a7ea65f5cafc3715c83f5b6829046 to your computer and use it in GitHub Desktop.
A simple explanation of the @autoclosure keyword
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
/*: | |
### Swift 3 @autoclosure | |
*/ | |
import Cocoa | |
// Let's suppose this is complex funcion with lookup database etc. | |
func nextOrderNumber() -> Int { | |
return 1000 | |
} | |
//: Let's create 3 different functions to build an order. | |
// This first funcion takes an Int as order number, so far soo god. | |
// The type is (String, Int) -> String | |
func buildOrder(customerName: String, orderNumber: Int) -> String { | |
if (customerName == "David Copperfield") { | |
return "Sorry we cannot create and order for this guy" | |
} | |
return "Created order n: \(orderNumber) for \(customerName)" | |
} | |
//This is how the first funcion should be called | |
//Pros: The function is straight forward. | |
//Cons: The expensive function `nextOrderNumber` is called even if the customer is "David Copperfield", we could save some resources there. | |
buildOrder(customerName: "David Copperfield", orderNumber: nextOrderNumber()) | |
// The second version of the builder takes a clousure | |
// The type is (String, (() -> Int) ) -> String | |
func buildOrder(customerName: String, orderNumberFetcher: ()->Int ) -> String { | |
if (customerName == "David Copperfield") { | |
return "Sorry we cannot create and order for this guy" | |
} | |
return "Created order n: \(orderNumberFetcher()) for \(customerName)" | |
} | |
//This is how the second function should be called | |
//Pros: The expensive function `nextOrderNumber` is not called until it's really needed. | |
//Cons: Nothing really, but a clousure parameter makes the funcion hader to understand. | |
buildOrder(customerName: "David Copperfield", orderNumberFetcher: nextOrderNumber) | |
// The third version of the builder uses an @autoclousure | |
// The function type is (String, @autoclosure () -> Int) -> String but it should be used as a `(String, Int) -> String` function. | |
func buildOrder(customerName: String, orderNumberFetcher: @autoclosure () -> Int ) -> String { | |
if (customerName == "David Copperfield") { | |
return "Sorry we cannot create and order for this guy" | |
} | |
return "Created order n: \(orderNumberFetcher()) for \(customerName)" | |
} | |
//This is how the third function should be called. | |
//Notice: An `int` is required as second parameter but, because of the @autoclousure keyword an eventual function is not called until needed. | |
// The way of the function is called is exactly the same as the first function, but the `nextOderNumber` is not called if not required | |
//Pros: The expensive function `nextOrderNumber` is not called until it's really needed. | |
//Cons: It can be hard to understand that `nextOrderNumber()` execution is postponed. | |
buildOrder(customerName: "David Copperfield", orderNumberFetcher: nextOrderNumber()) | |
/*: | |
### A more real case | |
*/ | |
//The @autoclousure can be usefull for logging funcions like in this example. | |
enum LogLevel : Int, Comparable { | |
case None | |
case Error | |
case Debug | |
case Verbose | |
public static func < (a: LogLevel, b: LogLevel) -> Bool { | |
return a.rawValue < b.rawValue | |
} | |
} | |
let globalLogLevel = LogLevel.Error | |
//This function takes an @autoclosure string as parameter | |
func log(logLevel: LogLevel, message: @autoclosure () -> String) { | |
if (logLevel <= globalLogLevel) { | |
//Call the clousure only if needed | |
print("DEBUG: \(message())") | |
} | |
} | |
//With this approach, we can log `anExpensiveFunction` calling the function olny when it' really needed. | |
func anExpensiveFunction() -> String { return "hello world" } | |
log(logLevel: LogLevel.Verbose, message: anExpensiveFunction()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment