[MUSIC] In this segment, I'm going to admit to you that Racket actually has mutation. In fact it has assignment statements, because we need them for some of the idioms we will be studying later in this section. But in this segment, I'm going to show you how they work and some of the problems they cause. Because if you use mutation in places you should not, bad things happen to your software. So Racket really does have assignment statements and we use them only where appropriate. People generally programming a Racket, do not use them a lot. But when they need them the Racket concert is called set!, it's spelled S-E-T-!, and everyone pronounces it set bang. And the way it works is set bang takes a variable that should already be in the environment and an expression e. It evaluates e to a result and it updates, it actually mutates what x is bound to? So anyone who's using that x in their environment after this set bang will see the updated value for x, all right? So any later look ups for x by anyone who's using that x, they'll see the later value. If they already looked up x, well they saw the value before we did the set bang. And this really is like the assignment statement and languages you may have seen before Java, C, Python and so forth. The syntax is just set bang with parentheses around it. Now once you have side effects like this, some times you want to do a bunch of things in order. I'm not going to use this in this segment, but I should show you that Racket in general has this form where you say begin. And then some sequence of expressions, and this is the sequencing operator. You do each of these expressions in order, and your overall result is just whatever the last one evaluates to. So these earlier ones are useless, except if they do set banging, they do any updating or any printing or anything with a side effect then we need to execute those just for their side effect. So let me show you an example of using set bang that's actually mutating a variable. So imagine this is a file and I want to sort of emphasize to you why this sort of assignment statement is probably a bad idea. So let's go through this line by line. On the first line, we create the environment where b is bound to 3. On the second line, f is bound to a function. But if this were ML, I would say f always, always, always adds 3 to its argument. Because given x, it does multiply by 1 and the addition of x and b, all right? So I made this big point that ML thanks to closures, this function will always add 3 to it's argument. Now, what I have to say is in fact, we still have closures. And this function will always, when it looks that b at this b, we still have lexical scope. But when it looks up b, it will get whatever the current contents of the b are. Because with set bang, we have to start talking about current contents. If you don't use set bang, you can forget that, the initial contents or the contents for all time, okay? Line 3, when we look up b for this expression, we use 3, so we get 7. So in the environment, c is 7 period. I have it here on the comment, c is 7. At this point we set bang b to 5. So hence forth b in this environment is 5. So now when we call f with 4, when the body of this function is executed, it looks up b in the environment and it sees 5. So we end up with 5 + 4, that's the + x b multiplied by 1, we get 9. On this last line however, where we just look up c and put the result in w, c is 7. We already did this plus before a long time ago, three lines ago. And what's in our environment is c is 7. Having done that addition, any subsequent changes to be are not relevant. So that is why z is bound to 9, because the call to f saw the new value for b. But w is bound to 7 because c holds the result of adding b and 4, where we looked up b before the set bang, okay? So when you can set bang, when you can assign to top level bindings, a lot of things can start going really wrong. So suppose that we thought that function f really was supposed to always add 3 to its argument. How could we fix that? Well no one programs this way in Racket. Do not do this on your homework. But I want to make a point about how if you had to deal with the potential of set bang correctly, you'd have to do a lot of extra copying of bindings. So a general principle in software development is if you're worried something might change, make a copy of it before it can change. And we can do that with our example function f. If we wanted f to always add x to the value of b when f was defined rather than the updated value of b when f is called. And what we can do is we can make a local copy. We can define f to be the result of this let expression. What this let expression does, is it initializes some local b that the outside world cannot get to in there for cannot set bang to be whatever the outer b currently is. So we have that 3 and now this function whenever called, we'll look up the find us local b. We already copied the outer one and we're fine. So you normally use the same variable when you use this technique. But if it confuses you this inner b does not have to be the same as the outer b, we could have said let c be b when the x times 1 + x and c. And that would've still made an appropriate local copy that would make sure that this closure is unaffected by any later set bang of this top level b. But it turns out that wouldn't necessarily be good enough, in a simple elegant languages design you'd say wait a minute. That function also uses addition and multiplication and those are just variables bound to functions. And if we have set bang, we have set bang. What would stop someone from set banging the plus variable to be bound to some different thing no longer the addition function? So now for our function f to be safe, we have to make a local copy of b and a local copy of plus and a local copy of times. So that we know that this function body down here when it looks up times and plus and b will get the code we want even if there's a later set bang. Nobody programs like this, don't worry about it. But semantically this is what you would think you would have to do. And then older Racket like languages like scheme, this would actually be a problem. If someone did a set bang of plus, all sorts of codes would start breaking, because they all assumed it was still the addition function. So the designers of Racket decided, this was just too much. We don't want to have these sort of problems creeping into our software. So in Racket you cannot set bang things like plus. They made a strange compromise that if the file that defines something does not set bang it in that file then nobody else can either. And since the file where plus is bound to the addition function does not have any set bang for addition. We don't have to worry about anyone else assigning to it either. Okay, let me be clear about this. I did not want you on the homework making local copies this. It's a strange idiom, it's not necessary. What everyone does in Racket is just assume that no one is going to do set bang of top level bindings. So why did I show this to you? Because I don't want you to use set bang on top level bindings in any language. Assigning to top level things that lots of your code might be relying on is just a bad idea. And if you don't mutate things, then you have much simpler semantics. And it's actually quite dubious whether in your language, you should even allow top level bindings to be mutated, and that's why we have set bang. But Racket went ahead and had some reasonable compromises about what you're allowed to set bang and what you're not.