Greetings, traveler!
We don’t use the @autoclosure keyword very often. It turns a function argument into a closure. But how can we use it? Let’s take a closer look at an example.
Example
Imagine we have a DataSource class that holds an array of data. For learning purposes, let’s use an array of CustomStringConvertible.
class DataSource {
var data: [CustomStringConvertible] = []
}
This protocol will ask us to add a property named description to any object that conforms to it. Let’s create one.
struct Vehicle: CustomStringConvertible {
let name: String
var description: String {
name
}
}
Now, let’s create a Logger, which will print any message into the console but only in the Debug mode. This means it won’t happen on the production build, which will be passed on to the App Store.
class Logger {
static func log(_ message: String) {
#if DEBUG
print(message)
#endif
}
}
In our DataSource class, there will be a function that helps to append an element to the data array. In that function, we will use our Logger to print out the description of the appended element. So, as an argument, we will pass our element’s description.
class DataSource {
var data: [CustomStringConvertible] = []
func update(with item: CustomStringConvertible) {
data.append(item)
Logger.log(item.description)
}
}
However, even though we do not use the printout in the console in the Production build, we still force the description property to calculate the value by just addressing it.
This is when the @autoclosure keyword comes to the rescue. Since it turns an argument into a closure, we can delay its request.
class Logger {
static func log(_ message: @autoclosure () -> String) {
#if DEBUG
print(message())
#endif
}
}
In this example, we will compute the value only after we call this closure.
Conclusion
Yes, this is not something we will use every day. However, understanding such a mechanism will help us think more broadly and design more optimized, high-quality code.
I hope you enjoyed this article. See you soon.