Swift closure, Starting of being creative



Coding is an art irrespective of this mindset, we all will agree that structural code is a pleasure to eye and joyful to work with. But why Swift yet not been so fluent to us? Why are we yet not been so impressed with Swift as others say so? Why we can’t see the beautification of Swift code? Actually we need not to have any special eye or any extraordinary viewing angle for enjoying the beauty of Swift code. Rather we need to extend our knowledge to have a good grab on Swift closure so that we can start understanding the code flow and the concise construction of that flow.

Why closure is essential

No doubt, closure is one of the fundamental component of Swift code. One who understands the closure, understands the whole code flow. The understanding of closure does not come up by chance. We have to have some study, have to spend some time on this topic. But it is certain that, the spent time on closure is a career booster. How?

  • Code written by professional suddenly becomes easier to digest.
  • One will start writing professional clear concise code, which co-worker will love.
  • Time is saved, tends to more productive hour for the employer.

Improved knowledge only on closure will move us far more further than that of which we think of, on the initial state of closure knowledge gaining. We have to travel a lot, have to listen a lot of talking. So let us not delaying any more. Les us dive deep.

Background

On Different variants of closure expression we will talk about:

Introduction of closure

closure is simply a chunk of code, start with a { and ends with a }. Yes that much simpler concept.

Only a code block within a pair of curly brackets! Then why it seem so difficult to understand? Well the reason is, the variances of closure. closure on Swift comes up in different forms and shapes which make the reader of the code, at least on the initial state, confused and even sometimes fearful for closure. But fear not. We gonna get ourself out from the unknown part of the closure. Once we know the variances of closure, life will become far more smoother 🍹.

So do we want an example? Sure why not.


let sum = {
    (first: Int, second: Int) -> Int in
    return first + second
}

sum(10, 20) //30

Above is a very simple example of closure, this closure will just return the sum of two Int. Ya ya we have a lot of questions. Those answers will come one after another. For the time being let us have some basic understanding of closure.

Explanation

As we said closure is contained with a pair of curly brackets, { }. So both the lines (first: Int, second: Int) -> Int in and return first + second makes the closure.

The very first line just after the first curly bracket or the opening curly bracket, {, is the closure declaration.

Ahhh one question, closure declaration sounds like a function declaration, is there any similarities? Well of-course there is. We will talk about this on the Function vs closure, the true face.

Back to our closure declaration talk, so ya we have the params and the return declaration just as the same way we used to have for function. Now the interesting part is the in. Seems like a very tiny word, but it has its value in closure. The in acts like a barrier among the closure body and the closure declaration. In other words, in makes the separation of closure declaration from its body. Now there will be closure where in will not be used. We will talk about those on the upcoming section.

Now the second line is very easy to understand. returning the sum of two Int. Wait wait return? Can closure returns just like function? Yes they can. Just like function, the return for a closure is not a certain occurrence. Some closure will return some will not.

This was the generic format of closure.

On Swift the power of closure comes from its flexible. The flexibility becomes a blessing for those who understand the ins and outs of closure. But for those a nightmare whom have knowledge gap on closure. So let us have some knowledge gaining on closure.

First class citizen support

So closure is a first class citizen on Swift realm. How? Because we can use closure as

  • params of function
  • returned value of function
  • stored property

Different variants of closure expression

As we said earlier, closure comes in on different forms and shapes. So we will have multiple expression of a closure. We will start from the very basic expression of a closure and then we will move forward gradually to a more advance expression. In other words we will start from the very elaborated expression of a closure and then we will make that closure more concise.

Question: Why we need to make the closure more concise?
Answer: Because concise is exact to the point in few words. Concise code saves a lot of time and energy of the developer. Plus it also beautify the code. Profession guys love the concise code as it contains no unnecessary junk.

We already have a prep talk on our Drilling HOF, Higher order Function blog post. Here we will have a more detail talk on closure expression.

Closure explanation through HOF

Here we will use one of the easily digestible HOF, Higher Order Function, to build up the case study of closure expression. We will use the forEach(_:).

Why easily digestible? So that we can concentrate only on closure.

Why HOF? Because HOF will take a closure to process the requirement, so it is ready-made. Moreover HOF like forEach(_:) takes a simple closure, makes it easy for us to grab the concept easily.

Now the declaration of forEach(_:) is as following:


func forEach(_ body: (Base.Element.Element) throws -> Void) rethrows

Ok not so simple one for a starter, but it will be. If there is any confusion on throw and/or rethrow we can always visit the Error Handling blog post for a clear concept on those two.

Let us remove the throw and rethrow from the expression, as this two are not our concern here on this blog post.


func forEach(_ body: (Base.Element.Element) -> Void)

Far more simpler now. As we can see forEach(_:) is a function which takes a closure as the param.Wait!

Question: what is the Base.Element.Element?
Answer: Base.Element.Element is actually a generic type element of the corresponding collection. We will have some future post on generic. As later down the road we will replace this generic type element with a more concrete type element.

Question: Is (Base.Element.Element) -> Void means a closure? Seems like a function definition.
Answer: Theoretically yes. Yes means, yes it is a closure. And also yes, this is like a function definition. Actually function is a special type of closure. We will have that talk very soon.

Now what is the plan with the closure in forEach(_:)? The plan is simple. We will feed the closure of the forEach(_:) with different closure-expression and will explain why and how of those closure expression.

We will use the prime array for our case study. And total is used to hold the sum of the prime.


let prime = [ 2, 3, 5, 7, 11, 13, 17, 19]
var total = 0

Elaborated expression

The elaborated expression or the most basic expression of closure for forEach(_:) is as following:


prime.forEach { (element: Int) in
    total += element
}

Let us break it down. As we said in breaks the body from the params, so here element is the param and total += element is the body. Moreover element represents the elements of prime, so element is Int as prime is Int. We are replacing the generic type with a more concrete type, Int.

Now can we make it more concise? Yes we can, continue…

Inferring type from context

We can drop the type Int from the closure param like following:


prime.forEach { (element) in
    total += element
}

Same as the previous section but this time no Int is present on the param. How this was possible? Because Swift can infer the type from the context. As prime is a type of Int so the element, elements of prime, will also be type of Int.

Implicit return

Let us consider another HOF, filter(_:), which has a return part with it.


func filter(_ isIncluded: (Base.Element.Element) throws -> Bool) rethrows -> [Base.Element.Element]

After removing throw and rethrow:


func filter(_ isIncluded: (Base.Element.Element) -> Bool) -> [Base.Element.Element]

So the isIncluded, (Base.Element.Element) -> Bool), is the closure part. And the [Base.Element.Element] is the return part of the filter(_:).

Now if we want to filter out the prime, greater than 7 then we will code as following:


prime.filter { (element) -> Bool in
    return element > 7
}

Have a look at the return statement. We already know the return will be a Bool from the closure declaration, (element) -> Bool. So can we omit the return from the closure body? Yes we can. So after omitting the return keyword from the closure body:


prime.filter { (element) -> Bool in
    element > 7
}

no return keyword 😃.

Shorthand Argument Names

What does Shorthand Argument Names means? Well shorthand means short and simple way of presenting. Argument is the synonym of parameter. And the Names is the title. So Shorthand Argument Names is a pre-formatter short way of expressing the closure params. If a closure has a single param then it can be represented as $0, for two param it will be first and second as $0 and $1 respectively and so on.

So our forEach(_:) and filter(_:) will be as following:


prime.forEach( { total += $0 } )

prime.filter( { $0 > 7 } )

Wow!!! tough to believe, right? so simple so concise. But those are the most simplest form of closure. Should we have something more challenging? Wait wait, we still have some others parts to cover to have a good understand on closure.

End Talk

Swift closure plays a very important role in Swift learning. This initial talk will start to synch us on that path.

All the source code used on this blog post are available of GitHub.

Stay tunes, we will have two more blog post on closure. The second blog post is a continue version of this one plus answering the relationship between closure and/or function. We will talk some more on that. Till then Happy talking.

2 thoughts on “Swift closure, Starting of being creative

Leave a Reply

Notifications for mobidevtalk! Cool ;) :( not cool