Closures, called blocks or lamdas in other languages, are blocks of code that can be passed around and called. They enclose the scope in which they are defined. That means any variable that is in scope with the closure is defined and is also still in scope when it's executed. Learn how closures are great for passing around into higher order functions.
- (Instructor) So there's a few things we want to discuss before we dive into the higher order of functions. First thing we need to talk about are what are closures? You may be familiar with closures but we need to really break it down. So, closures are self-contained blocks of functionality that can be passed around and used in your code. Closures in Swift are similar to blocks in C and Objective-C and to lambdas in other programming languages. But the take-away here is they're self-contained blocks of functionality and they can be passed around. So this is very helpful.
So it's like a little machine that can do something and you can pass it around and loan it to your friends. That's the great thing about closures is they're self-contained and they can be passed around. Now, closures capture and store references to any constants and variables from the context in which they are defined. So wherever a closure's defined, anything else in scope at that time, is in scope within the closure. So even though you declare a sign, a variable outside of the closure where it's defined, everything in that same scope is still in context for that same closure for when it's executed.
Again, it could be passed around, but it still has access to all those things when it's executed. This is known as closing over those constants and variables. Swift handles all the memory management of the capturing for you so that's handled, you don't have to worry about it. So let's look at a quick little example of how we might use closures and the purpose. So let's say you have a function, this is just a regular old function, takes a string and an Any and it returns a string. And we won't worry about the implementation, it just returns this encrypted string constant.
So here's your function, pretty basic, no big deal. But then let's say you want to have that function in something you don't want it just laying around. So you put it in a class called Encryptor. And you have that very same function in that class. Then in another part of your code you have this function called encrypt and it takes a string, and it takes an encryptor, and then it calls the encrypt function on that class instance and returns it. So it takes the Encryptor that's passed in and then it can call that function that it's really interested in and manipulate it from there.
So, pretty standard stuff here. But it sounds like the job for a protocol. You might want to be able to pass in different types of Encryptors at different times depending on the encryption you're using. So you defined a protocol called Encryptionator. And it defines the encrypt function. Your Encryptor already implements that function so it just has to claim that it implements Encryptionator as a protocol. We're all fine there. And now your encrypt function can take the string and the Encryptionator and call encrypt on it.
So it sounds like we're doing a lot just to really get down to that function, that's what we really care about, this encrypt function. It doesn't matter if it's in this class or that class or anything else, we really just want that functionality to encrypt something. So wouldn't it be great if we could just pass in that function as a type instead of the class as a protocol. Well that's exactly what we're talking about here. we just want the function. I want to be able to pass in a function to encrypt as the encryption function type say and then just call that.
Well that's where we are, that's where we're starting. And if it's a little bit confusing, that's fine. We want the fog to settle in and then we'll clear it away. We sometimes have to break you down before we can build you back up. But this is where we're starting and this is where the fun's going to begin.
- What are closures?
- Closures and function types
- Basic higher-order functions, including sort and forEach
- Powerful higher-order functions, including map and reduce
- Passing functions
- Closure optimizations
- Higher-order functions on sets, dictionaries, and strings