[MUSIC] Okay. In this segment, I want to talk about shadowing. Shadowing is when you add a variable to an environment when before you added it, that variable was already in the environment. So, to do this, we're going to end up having multiple variable bindings for the same variable in the same file. that can be a little bit confusing. It's usually poor style to do that, although it does come up with certain idioms. But it's going to be a great way to make sure that we really understand how environments work. So, I'm not going to give you any new rules, there's no new syntax or no new type checking or evaluation rules here. We're just going to use this idea of shadowing to really explain how environment and variable bindings work so that we have that solid foundation we need when we go to add things to the language. So, let's just start here by adding this binding, val a = 10 to our environment. And so, we know now that in the static environment, a will have type int. And in the dynamic environment, a will be bounded at the value of ten. And so, of course, if we then continued in our file with a * 2 b would have the value 20. I'm going to ignore the static environment here just for expediency but, of course, that's, that's relevant as well. [COUGH] So now, the interesting thing happens if we say, val a = 5, alright? And the thing I really want to emphasize, is that b is still bound to twenty. And, in fact, if I next said val c = b, even though right here, I had an environment where a maps to 5 and b maps to 20, now I have an environment where a maps to 5, b maps to 20, and c maps to 20. Because we know that the way you evaluate this expression b is you look it up in the dynamic environment, you get 20 and then you extend the dynamic environment so that now c maps to that result, alright? So, the fact that b was earlier created by evaluating a * 2 is no longer relevant. That was back in an environment where a mapped to ten. We got twenty, we extended our environment so that indeed a mapped to 10 and b mapped to 20. And that's the end of the story. The fact that we had a * 2 is no longer relevant. And I should emphasize as well, that this val = 5, this is not an assignment statement, okay? There's absolutely no way in ML to mutate or change the fact that a mapped to 10 in the previous environment. All we get is in the subsequent environment, a is now shadowed. We have a different mapping for a in a different environment and a is now five. So, that's the idea. Let's just do a little more examples to make sure we got it. If I now say val d = a I'm going to end up with an environment with all the things I did have and now d maps to five because a maps to five in this environment where I am. If I now say, what about val a = a + 1. Again, there's no such thing as an assignment and this makes perfect sense. The way a variable binding works is we evaluate the expression in the current dynamic environment. So, a maps to five, we add one to that, we get six and then we create a new dynamic environment where a maps to six along with everything else we had previously, but we're now shadowing the fact that a maps to five in an earlier environment or a mapped to ten in an even earlier environment, okay? So indeed, if we now say, val = a * 2 f will map to twelve. I should emphasize as well that something you cannot do is a forward reference and we know why for the same reasons. So, if I had this code here, it would not type check and the reason why is when I have to go to type check, this expression f - 3, f is not yet in the environment. So, when I look it up in the static environment, it's not there and now we've got a type error message. So, that's the example I wanted to show, let's real quick try it out and make sure that I typed everything in correctly. Oh, semicolon. Let's there we go, we'll try this again. Notice I didn't panic when I got an error message, there we go. And we see all the values I saw but for those earlier a's the read of all print loop is trying to be helpful and just say, you know, this value can't possibly be relevant to you. I know it's shadowed in the dynamic environment you now have down here where a is bound to six. So, rather than show you what a was back up in this earlier environment, I'll just print hidden value. Alright. So, that is the code example, let's go back to the slides here and show you again that in the key example here, when you have something like val, a = 1, b = a, a = 2, that in the environment you end up with b is bound to one and a is bound to two. There's actually two reasons for this, either one of which would be enough. the first reason is that we evaluated that expression we used for b, that expression a on the right hand side of the equals, eagerly back when we evaluated the variable binding for b. So, after we've done that expression evaluation, b is bound to one and it doesn't matter how we got that one. It will never effect the fact that we got a one and that's the end of the story. The second reason b will stay bound to one is that that second val2 = 2 is not an assignment statement. The earlier a, the a that leads to the environment that is used to evaluate b is still one. All we do is create a second variable b that shadows it. So, it turns out, this is the reason I'm so insistent on not having use commands in your RPL more than once for the same file. Because if you say use multiple times for the same file, you're going to repeat whatever bindings were there the first time you said use for the file and they are still there the second time you said use for the file. And while it's legal in ML to have that sort of shadowing and to reintroduce those bindings, it can be really confusing, right? Maybe you took a binding out but it's still there because of the previous use or maybe you have some strange shadowing that makes it look like your code is correct when, in fact, you're it's, it's wrong because of how the shadowing happened to work for the multiple use statements.