Closures in Swift and how to break them…(Pun intended)
When learning something new (it doesn’t matter if you’re a beginner or not), it is hard not to follow the “need to know it upside down” trap…And the trap can be imposed by yourself, and your personality type, but it is more often implicitly imposed by others (experts opinions, your colleagues, your teachers, you name it). Been there…done that… I’m 45 years old, and only a couple of years ago I’ve managed to start jumping over that trap. I guess for most of people, it comes with age. You start to mature and put things in perspective. I could write an essay about this topic…
Why this intro? It has nothing to do with Closures. But it has at the same time. I can only speak for myself here, but it is hard to find an article or a tutorial about Closures where the author assumes that you know nothing about it. It usually starts by saying that it is a hard topic, and once that is aside, soon the “trap” begins. The doors are open and the flood of possibilities and details around the topic will grab you and there’s nothing you can do. Not even to get rid of the trap. Don’t get me wrong…Most of the articles are great!!! I’m sure when I understand them, they will be even greater!!!
Enough of trying to be funny... My goal today is to try and keep it as simple as possible and to break down a Closure and its meaning and application, without the complication usually associated with it. The ideia for this article came when I was watching an Angela Yu’s video in her Udemy’s course. Actually credits to her. I will not copy what she said there, but the approach will be similar.
So, what is a Closure?
A Closure is a Function. First you need to realise that. Then you need to understand that is a Function, but most of the times is anonymous, and you don’t even need to name the parameters or to declare the return type. Also it “lives” inside another Function…And there’s when the confusion starts. At least for me. When I see a Closure’s syntax, I’m lost…
So what we’ll do now is to use a Function as an example, and break it down until it is a Closure. Step by step…
So we have a simple Function that will check if 2 words have the same number of Characters and then return a String with the answer. For that we have “firstWord” as a String, “secondWord” as a String, and instead of doing the verification inside the Function, we will have another parameter, “validation” to call another Function to do so. I know we could do it inside the Function, but to show you that we could call a Function as a parameter inside a Function we’ll do it this way.
Then we need to have the Function that will check if those 2 words have the same number of Characters.
Finally we need to call the initial Function to get our result as a String. So for “Mars” and “Venus”, we get “Different number of Characters”. Simple and working.
So the first objective here is to show you that it is possible (and really useful) to use a Function as an argument of another Function. The next steps will be to show you how to streamline the code until you get the minimal syntax of a Closure.
Let’s focus first on the Function that will be “transformed” into a Closure.
The first thing we need to do is to remove the name of the Function and to place the curly braces BEFORE the parameters and add the expression “in” to the syntax (Ignore the compiler erros for now).
Now, when we call the main Function, if we replace the validation parameter with this new piece of code (this is now a Closure), we get rid of the errors and we get the same result as before!
That’s all good, but I don’t see much improvement or benefit by doing it this way. That is why we should keep going and rely on good Swift intelligence!!!
I’m sure you probably heard about Type Inference. So let’s try and use it here. If we remove the Type Declaration on parameters word1 and word2, Swift still gets that must be a String and move on. And while we’re there, why don’t we do it also with the Return Type?
Great! Still working and less code needed to run our Function! and we are still getting the same result “Different number of Characters”
With Closures, the compiler is smart enough to work with anonymous parameters. In Swift, if you want to call the first parameter of a Function you can simply use the dollar sign $ and zero 0, $0. The second parameter $1, and so on if needed. If we apply it to our syntax, we can streamline it even further.
Do you want to reduce it even more? You’re in luck, because there is a rule in Swift, that will help you out to achieve that. If the last parameter of a Function is a Closure, you can omit the parameter name when calling it. More! You can even trailing it at the end of the Function you’re calling!
So, let’s resume what we did. We started like this:
And ended up like this:
If you look closely, what we did here was to pass the external functionality to the body of our call!!!
It might not seem like a great improvement, syntax wise. You can also argue that this could be done inside a Function, without the need of another Function. You’re right. But let’s get back to the beginning of the article. The main goal here is to simplify a concept and make it as easier as possible to follow. Because if you understand these simple steps and its meaning, you are much closer to understand when things get a lot more complicated. At least works for me. I just hope that it can help you as well!!!