Swift provides the @autoclosure
declaration attribute. When applied to a function parameter type, it converts the call site expression into a no-arg closure with a return value, delaying the evaluation of the expression. For example, in the following code, both normalFunction()
and withAutoClosure()
are called with the output of foo()
, but because withAutoClosure()
's argument is declared as @autoclosure
, it doesn't evaluate foo()
. Instead the foo()
call is wrapped into a closure which is then passed to withAutoClosure()
.
func foo() -> Int {
print("foo called")
return 1
}
func normalFunction(_ i: Int) {
print("normalFunction:")
print(" Value returned by foo: \(i)\n")
}
func withAutoClosure(_ fn: @autoclosure ()->Int) {
print("withAutoClosure:")
// print("value returned: \(fn())")
print(" Notice foo is not called?")
}
normalFunction(foo())
withAutoClosure(foo())
This will produce the output:
foo called
normalFunction:
Value returned by foo: 1
withAutoClosure:
Notice foo is not called?
Using @autoclosure
, you can decide to skip the evaluating the expression or evaluate it one or more times. The Swift blog gives an example of implementing assert()
using @autoclosure
, as well as short-circuiting logical operators.
Note that @autoclosure
has to be used judiciously because the someone reading the code cannot easily determine that the argument has @autoclosure
applied to it.
PS: This code is written in Swift 3. Minor modifications would make it work with Swift 2.2
PPS: If you have any interesting (and short) tip you would to share or a feature you would like me to talk about, reply to this email
Your feedback is valuable: Do you want more nuggets like this? Yes or No
.
.