Module 2, function types, topic 1.2, returning functions. Functions can also return other functions as their return value. So why would you do such a thing? Okay, that's a good question. One reason to do it is if you want to make a new function that's sort of a special purpose parameterizable function. So you want to change something about the function according to some kind of input data. You want to make a new function that acts differently, that is parameterizable. So you can create that, you can have a function create a new function which has a different set of parameters. So to give you an example of something like this, and by the way, I'll admit, it took me a while to think of this example, okay? So this isn't a common thing that people do a whole heck of a lot anymore. But I can imagine uses for it, and it's kind of interesting to think about it, about all the things you could do once you start thinking about returning new functions that have different properties. Okay, so here is my example. I want to find a distance origin, I want a function that computes the distance in to the origin. So, it takes a point, x, y coordinates of a point, and it returns a distance to the origin. So basically it's going to perform Pythagorean theorem to find the distance, right? Now, what if I want to be able to move the origin, right? I remember vaguely in physics, you might want to move the origin. Maybe I don't want it here, I want it on top of the car, depending on the problem, right, which is moving, who knows. But I might want to change the origin. So the distance to the origin is going to change depending on what the origin is, right? So I can think of the origin, the location of the origin as a set of parameters to this function. And I would like to make a new function, a function for each different origin. So maybe I want a distance to origin function that assumes one origin. And then another distance to origin function that assumes a new origin. Maybe the origin is moving for some reason. Which actually happens in physics. So let's take a look at how we might do that. So a way we do it, is we can make a function that defines a function and it returns a function. So this function is called MakeDistOrigin, right? And the point of this function is to create the function that I want, this distance to origin function. So if we look down at the bottom of this function, you could see it says a return fn, right? So what its going to do is its going to define a function inside it, and then it's going to return that function as its return value. So let's look at the, go back to the top, make this into origin. It takes several arguments, okay. The arguments right there are o_x, o_y, right? These are two floats. Now, these two floats, they're supposed to be the origin. The o stands for origin in this case. So the o_x and o_y are the origin location, right? So if I want my origin to be 0,0, those first two arguments would be 0,0. So wherever I want my origin, I pass that as arguments to this MakeDistOrigin function. Now, the return value of this MakeDistOrigin function is a function. And you can see that in the second line, line 2, func at two arguments float64,float64 returns one float64. So the two arguments of this return value of the two floats are going to be the x and y coordinates whose distance we want to compute to the origin. And then, the last float64 is a return value which is going to be a float which is the actual distance, okay? So just get this straight, this make distance to origin function, it has two arguments which are the x, y coordinates of the origin. And it has a return value which is a function, which is going to compute the distance to that origin that we passed as arguments. Now, if we look into the function, line three. We have a variable called fn, and that's going to be the function that we're creating. So fn: equals, and you notice we're defining a new function, func x, y to floats and returns a float. And this new function that we're creating, it returns math.square root, so it computes square root. It's doing Pythagorean theorem. Math,pow x minus o, x, right? So I take the difference between the x coordinate and the origin. And the origin's x. And I square that, and then I do the same thing, I add that to y squared. So it's y minus it's origin with a y component of the origin, squared. And then, I take the square root of that. So that's just Pythagorean theorem. It does its Pythagorean theorem, and notice that it take the x, y coordinates that you want to find, whose distant you want to find from the origin. Subtracts x from the origins x, y from the origins y. Does the Pythagorean theorem. And then, it returns that function. So this MakeDistOrigin function doesn't actually compute the Pythagorean theorem, it returns a function whose job it is to do Pythagorean theorem, to compute Pythagorean theorem to figure out the distance from an origin, o, x comma o, y. So this is a function that is made special purpose, this actually creates special purpose functions. So notice, I could use this function, this MakeDistOrigin function to make many functions. I could make one distance to origin function that computes a distance to one origin. I could make another one that computes the distance to a different origin. So I can make as many as I want with different origins. And so, the origin is now built in to the return function. Okay, so now, let's look at how we might use this. In my main, I'm going to create two functions. I say, look, I want to have origins. I want to have origin 0,0 and another origin at 2,2, for one reason or another in my problem, I need two different origins. So Dist1 is going to be the function that computes the distance to origins 0,0. Dist2 is going to be the function that computes the distance to origin 2,2. And you can see me define those in the first two lines. I just call MakeDistOrigin with 0,0, and then 2,2. Then the last two lines, the print lines, they just print, they compute the distance from 2,2 to the origins. So the first one uses Dist1. So it computes the distance from 2,2 to the origin 0,0, which is about 2.1 something. So that's what we'd print out. Where the second one computes the distance from 2,2 to origin 2,2, which it should be zero. So you print that out and you get zero for that. So what we've done is we've made two special-purpose functions. And we made them special-purpose by giving them parameters, specifically the origins, right? The origins are the parameters that we use to make the function. So this is somethings that's kind of a cool use of returning a function, right? A function can create a new function that serves sort of a catered, special purpose. Now, every function has an environment. An environment Is a set of all the names that are valid inside the function, okay? All the variables and other things the you define that you can refer to inside that function. So this includes all the names that are defined locally in the function, any variables that you create in the function. But also, it uses Lexical Scoping. Is lexically scoped. So what that means is the function can access variables that are defined in the block where the function is defined. So in the example code down there, we got this function foo. Now, the variables that I have highlighted in red, those are all inside its environment. So let's take z. z is defined inside foo, so clearly, it's within foo's environment. Actually, notice how I use the words scope to refer to environment? People do that all the time. It's very common. It's not technically correct. I think you're supposed to use the term environment rather than scope. So anyway, the variable z is defined inside foo. So it's inside foo's environment. The variable y is a local variable to foo. It's one of it's parameters, right? So that is also inside the environment of foo. So foo can access y and z. Now, the variable x is defined in the same block as the function foo is defined, so foo can see that variable x, too. So let's say this whole, this piece of code is all defined inside another function, right? This variable x is defined in the same place, the same block, as foo is defined, and so foo can have access to that, too. So all those variables highlighted in red are within the environment of foo. All the variables that foo has access to and can use when it's executed. So that's what environment is, and that's important. When you start passing around functions as arguments, the environment goes along with the function. So, this term Closure. A Closure is a function plus its environment, right? Together. In fact, in Go, I think it's implemented actually directly as a struct. You have a pointer to the function and pointed to the environment, and they're put together. So when you pass a function as an argument to another function, you're also passing its environment with it. So what that means is when you eventually execute this function that you just passed, it still has access to its environment, the environment where it was defined. So what implications does this have? Sometimes it makes figuring out the variable values kind of confusing. But just remember that the closure, the environment to that function, goes with the function when you pass it as an argument. So let's take an example. This, again, is a make distant to origin function, right? Now, the function that it defines fn equals func, that function, that function, it has and environment. And notice that o underscore x, and o underscore y are part of its environment, okay? That's important, right? They are a part of its environment. So when you execute that function later, so this make distance to origin, it's going to return this function. And later on, when that function that you return gets executed, it still has access to the same environment. So o_x and o_y, that it had when it was defined, they were paths to make distance to origin, those variables are still accessible to this function when you call it later, okay? So that's why, so basically what I'm saying is it remembers these origin values. The o_x, o_y, that gets carried with the function. And so, when you execute the function, it's still using the same origin values, o_x, o_y when it gets executed. So that's called a closure. And when you pass a function as an argument, you pass this closure, the function plus its environment together, they go together. So you have to remember that when you're trying to figure out how these functions get evaluated. Where are the variables are coming from, they're coming from this closure, from where it was defined, because that's how Golang is scoped. It's lexically scoped, so it gets its environment from where it was defined. Thank you.