Expressions

It took me probably longer than it should have to understand closure syntax. With them being able to be written in so many different ways, in the beginning it was hard to understand exactly what I was looking at, so I avoided writing them unless I had to. Theres a lot to digest, especially if you’re just beginning learning Swift. You have to at the very least be familiar with parameters, type inference, and returning values. If you’re not, understanding where everything goes, what can be inferred, and what parts of the closure can be removed because it’s being inferred is just impossible.

General Closure Expressions

Let’s start off with general closure expressions, which are probably the safest to learn. The expression looks like this:

{ (parameters) -> (type) in
   return value
}

An example of this expression in action would be:

let nameGeneralExpression = { (firstname: String, lastname: String) -> String in
    return "\(firstname) \(lastname)"
}

In a general closure expression, everything is explicitly stated. Notice the parameters each have explicit types, and so does what’s being returned. But Swift is smart, and we can use type inference to shorten these expressions quite a bit.

Inferred Closure Expressions

With inferred expressions, we can let Swift do a little heavy lifting and remove some information because Swift is smart enough to assume what you’re trying to do in most cases. Heres an example of what the expression looks like

{ (parameters) in
   return value
}

And here’s an example of that expression in action. Notice that the return type is completely removed.

let nameInferredExpression = { (firstname: String, lastname: String) in
    return "\(firstname) \(lastname)"
}

When explicitly stating the type of String in the parameters, theres no need to state a return type, because Swift already knows thats what has to be returned. We can take this a step further and remove even more code.

Implicit Return Closure Expressions

Because this type of closure is simple, and written on a single line, Swift is smart enough to infer that what’s written inside your closure block is what’s being returned, so we can remove even more. Heres an example of the expression

{ (parameters) in
   value
}

Heres what that looks like in action

let nameImplicitReturnExpression = { (firstname: String, lastname: String) in
     "\(firstname) \(lastname)"
}

In simple single line closures such as this, you can remove the return keyword altogether. Believe it or not, we can reduce even this to something much, much shorter. I present to you short hand closure expressions.

Short Hand Closure Expressions

These are going to take some getting used to, and you have to remember. The goal is always to write clean, readable code. The more you infer, the less obvious what’s going on is to someone who is not the person who wrote the code, which can be bad in team environments. To be able to accomplish this, Swift has to be able to infer the types of the parameters, and return types, which means you have to state these things explicitly with type annotation.

Think of it like this, in this example, I’m telling you that name has to be a string.

var name: String

This is the same as me telling you that a closure has to be a certain type as well. If I write:

let closure: (String, String) -> String {
}

It means that to use this closure, you must give it two parameters of type String and have it return a String. We’re giving our closure a type, no different than if we were giving a variable a type of Int.

This is the shortest form a closure can take, and thats accomplish by also using shorthand argument names. You can use $ and a number for your parameters. So your first parameter would be $0, and your second parameter would be $1 and so on.

Heres an example of what that expression looks like.

let nameShorthandExpression: (String, String) -> String = { "\($0) \($1)" }

It doesn’t get much shorter than that. But as you can see, readability of:

let nameShorthandExpression: (String, String) -> String = { "\($0) \($1)" }

Is nowhere near as clear as:

let nameInferredExpression = { (firstname: String, lastname: String) in
    return "\(firstname) \(lastname)"
}

So you have to pick your battles.

Stay Fresh

Xcode Shortcuts That Will Make Your Life Easier

5 Tips Every Beginning iOS Developer Should Know