Start a personal dev blog on your domain for free with Hashnode and grow your readership.
Get Started

Replacing @autoclosure in Swift

Before I start with this: I really love Swift! It is the best language in my eyes that is currently available. But I also hate a lot of stuff about the language design that I would like to help getting it fixed.

One of those things is the way @autoclosure is implemented. But let me first explain what it is and why it is needed. Imagine you have a function that takes a boolean value and a string. If the boolean is false it prints the string to the console, otherwise it does nothing. This function actually exists and is called assert, it also stops the execution of the program.

func assert(_ condition: Bool, _ message: String) {…}

The problem with this definition is, that the message might be heavily computed because we need to have a lot of information if the condition fails. Since Swift is strictly evaluated (every computation is done when the execution pointer reaches the line) this would mean the heavy computation is also done when the condition is true, so it would be useless since the string is not needed.

A way to fix this is to use a closure that produces the value instead of the value itself:

func assert(_ condition: Bool, _ message: () -> String) {
    guard !condition else { return }
    print(message())
}

This would only produce the value when it is needed. Since message is now a function instead of a String, we need now to call the function to get its value.

On the call side this changes a lot:

assert(something > 0, { return "something is \(something) 😱" })

This is not great and that is where @autoclosure comes into play. It wraps the given value automatically in a closure so that you do not call the function differently even if it is now using lazy evaluation. (lazy evaluation is the name for evaluating an expression only when and if you need the value)

I worked a bit with Scala recently and saw that they have a similar functionality in the language but I like the implementation much better. Here is the same function from above in Scala:

def assert(c: Boolean, msg: => String)

A normal closure declaration in Scala is pretty similar:

def function(f: String => String)

So in the end they only omit the parameters in the declaration. Parameters are also not possible for @autoclosure because the value needs to be produced without any if it is not written in a closure.

I really like this syntax and would love to see it in Swift as well! What do you think about it? The proposed solution would be to replace @autoclosure with this:

func assert(_ c: Bool, _ message: -> String)
Start a personal dev blog on your domain for free and grow your readership.

3.4K+ developers have started their personal blogs on Hashnode in the last one month.

Write in Markdown · Publish articles on custom domain · Gain readership on day zero · Automatic GitHub backup and more

Comments (3)

Moritz Lang's photo

Thanks Ben! Very nice and short explenation :)

Benjamin Herzog's photo

Thanks! What do you think about my proposed change?

Moritz Lang's photo

I could see it coming in handy, so I would appreciate the change :)