Clicky

iOS Dev Nugget 204 Swift @autoclosure

.

Need to run a code review on your codebase? Hire me

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

.

.

Like this and want such iOS dev nuggets to be emailed to you, weekly?

Sign Me Up! or follow @iosdevnuggets on Twitter

.

View archives of past issues