 Packed class today with practice midterms. Yay. Yay. Yay. Midterm on Friday. Yay. Yay. This is messing with me. OK. So the homework for solutions are posted on Blackboard under content, just like everything else. So you can go there and check out questions on homework board. Eight questions before we start today. Do the practice midterm and answering questions along the way. OK. Very important thing on any exam. I must have said this before. Did you steal these? No. Oh, cool. I guess I shouldn't ask that question because I don't actually want to know the answer. The answer is yes. Just want to use it. Somebody tell me how many possible combinations I can put this in wrong. I think it's four. I think it's just four or three. I did every single wrong way. OK. Yay. Awesome battery. Thank you. All right. Let's rock and roll. OK. Very first thing you should do on any exam. Put it in your name. I literally have a student in my grad class who did not put their name or ASU idea on their midterm. I'm considering it. Or I'm considering lording it over their head for a little bit. Because how do I know it's actually their midterm? I have literally no way. Of course, they're the only student who came forward that said that they didn't get a grade on their midterm. But still, how do I know it's them? Do I do like a handwriting test? If you get a hands-to-cheat in the book, you can take your exam and get the name. Yeah, exactly. Yeah, that would be super cheap. But that would be like calling more attention to yourself. So it would be self-defeating. OK. Let's not talk about this. OK. So we have problem one. We have a function definition here. So we have a function F that takes in four parameters. B, C, D, and E. And the program looks like this. So if D of E, then we do 3.14. What's going to be the type of this 3.14? Real. Real. Yeah. I'd probably also take double if you did that. But it should be real. Real plus E bracket B called with 10 E, L, C, D. So what is this doing? It's calling a function. What is this function return? A function. A function that we can see here based on the usage, exactly. And inside that function is being called E0. So we are just going to apply our fun little rules that we've been doing just to solve this problem. So I see a function definition. I know, OK, the type of F is going to be a function that takes in T1, takes in a T2, takes in a T3, and takes in a T4. 1, 2, 3, 4, and returns a T5. I also know that this node here, the type of this node is a T5. And from what I've been doing here, I know that B, currently, I know it's a type T1. I know C is of type T2. I know D is of type T3. And I know E is of type T4. This is what I got so far. It was just looking just at this top node, right? And so some of you, part of the way you can get in trouble with this is if you bring your own preconceptions about what should or should not happen, right? You start looking at this, and you start saying, well, T5, but then there's a call here, and then there's this other thing, but this is that bracket. Just take it one step at a time, one node, one layer at a time. Like, if it helps, literally, you can block out with your hand, which I can virtually do here. Oh, maybe I can simulate like this, right? So you can just consider just as function this very first layer of this tree, right? That's the only thing that matters right now. That's the only thing I've written down. Then we go to the if statement. So we know that an if statement, the left branch, this means this must be a pool. And then we know the true branch and the false branch must both return the same thing. What is the same thing that they're going to return? The T5, yeah. So we know that they have to return a T5, which is also the return value of the function F. All right, let's take the Boolean. So the Boolean is a call, right? So we're calling function D, and we're implying E. Sorry, we're passing it as the first parameter to D, E, and the return values are whatever the return value of this call node is. So then what does this mean about D and E? What do I know here about these two nodes? Yeah, D must be a function that takes in a T4, a type E, and returns a Boolean, right? So I have basically, I have the type equation that D, which is a T3, right, is a function that takes in a T4 and returns a Boolean. So I need to make sure that for all the types that I'm keeping track of that this is true. So I'm going to actually remove T3, so I have no more T3s. And I'm going to say D is a T4 goes to Boolean. So now I've completely gotten rid of T3. There are no T3s in my program anymore. OK, done with this node, then we'll go down this tree. So let's do the plus here. What does the plus operator mean? It means that both sides of it are, well, it means that the plus left side and right side are all the same type. The left side is the same type, the right side is the same type, and also the return of plus, right? The plus itself is the same type. So these are all T5, right? And then I go visit this node and I say, oh, T5 is actually a real, right? So now I have the constraint that T5 must be the same thing as a real. So now I can replace everywhere I have T5. I'm going to replace it with the reals, right? Because now real is more specific than T5. T5 could be any type, but we know it has to be a real. So let's get rid of that here. We were rid of it on the next node. Actually, we'll get rid of it here. And the important one is that this T5 becomes now a real. Well, I guess I did do something bad, right? I actually started solving this problem without ever reading what this question was asking me to do, right? So maybe it would just ask me what's the type of 3.14. So it's asking for the types of B, C, D, E, and the type that F returns, right? Let's go to this stream. So here we have a real, right? We have an array access operator. So what does this tell me about its children? Right side returns an int. Right side must be an int. And the left side? Array of reals. Array of reals, yeah. Right? So E, I know, must be an array of reals, which means T4 is now an array of reals, right? Which means this actually D is now, I actually know more about D, right? D is not a function that takes in anything. It's a function that specifically takes in an array of reals and returns a Boolean, right? So we've got that one. Now here we go to another function call. So here we're calling the function B and we're having the parameters, the first parameter is 10, the second parameter is E. Right? And we know that it must return an int, right? So from this, I know the type of B must be an int, right? This first parameter, E, which is an array of reals, and all of that returns an int. So B was a T1. If I replace all T1s in there with this. So we've gone all the way down this tree. This is the only part of the subtree that is left. So here we have a call function or we have a call, right? So we're calling some function and we know that whatever, so let's erase that, right? We know that whatever this function returns is a real. So we don't know what this left node is. We actually didn't number the nodes. So let's number this 1 and we'll number this 2. So we'll say that, before we try to figure this out, we'll do that 2, right? We don't know what 2 is yet. We need some new types. Let's say T6, I think we're at 6, yeah. T6, and so we know that 1, right? We know that the type of 1 is a function that takes in a T6 and returns a real. So now here, so which one node do you want to visit first, 1 or 2? Because it's a choose your own adventure. We should do 2 first because 1 has a parameter. But maybe going down 1 will tell us what that parameter is. Well, maybe not, but, it honestly doesn't matter, right? We can do either one. Okay, we go down 2. We know that this is a T6. We said this is type T6. And we say it's an array access operator, right? Which means that whatever the right side is, must be an int. Is it? Yes. So 0. And the left side, we know is what? An array of T6. T6 is. Right, exactly. This just says this must be an array of T6. We also have the constraint that this array of T6 must be the same as E. So this means that T6 must be a real. For these to be the same. Right, so I know now that T6 is now a real. Then here, so now I have to go back because this is the last thing I've got to do. Right, here I see a call function. So our calls. I'm calling the function C and I'm passing it the parameter D. So D is a function that takes in an array of reals and returns a Boolean. So we just think, okay. So C, I actually don't have any type for C, it's just a T2 at this point. So C, I know it's got to be a function because it's using a call here. I know it takes in a type of D. Type of D is an array of a function that's an array of reals that returns a Boolean. So this would be array real that returns a Boolean. This is the first parameter to function C and then what does C return? The return value is used as a call to a function. If you return to real, you'd be trying to call a real as a function. It returns one. It returns one, which is a function that takes in a real and returns a real. So this whole thing returns real which returns real. You kind of want to go, so it's a function that takes in a function and returns a function. This is lambda calculus practice. This is all lambda calculus stuff. So now I've gone through it. I can fill in all the types. So I know B is a function that takes in an int. It takes in an array of reals and it returns an int. Actually, I'm not going to fill this out because I think it should be clear. We've done everything we need to do. So this is the type of C. This is the type of B. This is the type of D. This is the type of E. And the type of F returns, we know F returns are real. Questions? Yes? I was just wondering, how long is this supposed to take us? Because just so that I know if this comes up on a test, how much time do I allocate to this before I move on to the next one? That's a very tricky answer, the question that I don't have a good answer for. Would it take me shorter because I'm not narrating exactly what I'm doing? Yes. I'm also teaching the class so you'd expect me to do it longer than it would take you. But you should be comfortable enough. The key here really is in this part. To me, that's the key. And part of why this is the key is knowing that here in this call it must return a function. It can't return real. So those are really the concepts that I'm teaching. I want you to learn. And so if you're comfortable doing this, you can just do these very mechanically and say, okay, this is reals here, reals here, functions here. So I think it's more dependent on you and how much time you put into it. So I think you've got to weigh that when you see all the questions and go, okay, where do I want to spend my time on? One of the things, talking game theory, look at all these things and say, okay, the type that F returns and you look and you can tell very quickly that F must return a real. You can put real down for that one to get points. So you don't have to give the entire thing of saying like F takes in T1 and what else? No, no. We just want the final types here. But you have to be careful, right? Because if, you know, just eyeballing this and trying to figure it out, a lot more difficult. But hanging the types on all of the nodes in the tree to me helps a lot. There's another question over here. On two for an array operation, if your index is a negative number, would that be a type error or would it be like... What's the type of a negative number? What's the type of, think about it like this, what's the type of, if you saw this, let's say it's a zero. What would the type of that be? An n. An n, right? What would the type of this be? That's also an n. Yeah, so what would the type of this be? An n. Right. But like you can't access in an array, you can't access negative one type error. That's, yeah, that would be more of a semantic error. Okay. And actually in some languages you can. So like in Python, negative indexing means you start from the back. So negative one would be I want the last element to the array. Okay. So yeah, it's kind of, could you make a type system to support this? Possibly. Yeah, you could. So if it's a negative number, then it doesn't grow a type error. Exactly. Yeah. You know how you drew this type for each of the nodes and all that? If we did that and got like one of the questions wrong on the midterm, would that be useful for partial credit? See what we've done? Possibly, but probably not. It all depends. You know, we do our best, but sometimes like, sometimes hammering is bad, sometimes it's not clear exactly where the problem is. Sometimes it's clear that problems fall into certain categories, right? But, you know, that's just the way it goes. Another thing, this facility said to reduce all types to basic types and type constructors if possible. Right? So this would mean when you do the type of B, right? We know that B takes in a type of E here as the second parameter. So if you put in as the second parameter here type of E, like TE, you're going to get docked out points, right? You're not reducing that fully down to what it is. Yeah. So there's no type errors in this because we're calling D with the parameter inside the F. But then we're just using B as a parameter for C. Wouldn't D also need a... There? Yeah. Here and here? Here it's being called as a function. Here it's being passed into a function as a function. Right? Where did we get B, C, D and E? Function called. From... They were parameters that are passed into this function. Right? They're not... Function B, C, D and E, they don't exist. Okay. Right? There's not like a defined function C. Right? They're passed into our function just like how we can do that. We can do the same thing here by passing... By calling a function and then passing that function as a parameter to another function. Okay. So we're allowed to not have parameter there always. Yeah. It's just a value, right? It's just about the types. So we know that based on the usage, D must be a type function. Right? And it has certain parameters. And so we know because of that when we call C, C must take in whatever the type of D is and D just happens to be a function. Okay. Yeah. Just like arrays, right? So it's nothing different than arrays. Like here we have an array, E, right? We know it's an array based on the usage and we can pass that array into another function. So arrays functions, no difference. It's a very tricky question. So this is actually a literal question from the final last year. It... I would probably have a way for you to say that it was a type error. Right? I would probably mention that in the description somewhere. Otherwise we're going nuts trying to figure it out. Yeah. But if you're adamant that it's a type error, then write down type error. Like that's fine. But there's implicit clues in questions and how questions are asked, right? Yeah. So when you first call the function and you pass those parameters and we don't know that they're functions. What do you mean when you first... These parameters? Yeah. We don't know their functions until we actually use it. Until we use the type check. Then we update them. Yes. So when you write the definition for f, you write it as a full definition with the functions. Yes, you write the full definition. With the functions. If I asked them the type of f, you would do the entire thing with t1, t2, t3, t4, all expanded to what they actually call them. Okay. And everything, if there's functions inside there, you define those two. Okay. Yeah, fully extended. Okay. On to problem two. Back to other type systems, structural types. So here we have our type declaration section and here we have a bunch of variables. Right? So we want to know, questions asking us for each of the following types, list the types that are structurally equivalent. So this is testing structural equivalents. And we'll get to this one in a second. So this is b is a string, c is a pointer to an int, b is a pointer to a b, e is a pointer to an i, just down here. f is a structure, g is a structure, h is a structure, i is a structure, j is a structure, k is a structure. Okay. So it's specifically asking us about b, oh, the types that are structurally equivalent. So b, f, what's structurally equivalent to b, what's structurally equivalent to f, what's structurally equivalent to h, and what's structurally equivalent to j. Okay. How do I do this in a way? Or do you scratch paper here? I want to just have this start a new page. Let's think. Then I have to flip back and forth. Okay. Let's do b, c, d, e. What do you have here? It'd be nice if you had one page on that side. If I use the white board, then it won't be recorded. They should be here. Parts forward to everybody online. All right. Let's make this a little easier for ourselves. So I can make this huge table, right? And I can do the type equivalence of everything on that table. But what do I already know? Can b ever be type equivalent, or structurally equivalent to, say, c? Why not? It's a pointer, and this is the basic type, right? What about f? F through k? So what's structurally equivalent to b? Yeah, or b, right? You can probably put it on too, right? But b is also structurally equivalent to b, right? So let's think about c, d, and e, right? They're all pointers. So I do want to find out what they're structurally equivalent to. I want to, because the problem is asking you to. Are they ever going to be structurally equivalent to any of f through k? No, no, no. No, they're not going to be structurally equivalent. So I can build my table, right, with only those elements, at least for right now, right? I can do a c, d, e. I can do a table like that. c, d, and e. c, d, and e. Right, that's going to be just for my pointers. And I can actually build the same table for g, h, i, j, and k. Right, because I know there's no possible way they could ever be structurally equivalent. And you, so you don't have to do it this way. You can totally do the big table. Just one pass through is going to give you these exact same results, right? It's really taxing my alphabet knowledge. Okay. So what do I assume when I do structurally equivalent? Structurally equivalent to structurally equivalent. Hmm? Everything is structurally equivalent. Everything is structurally equivalent, yeah. What do I assume? Yes. True, true, true, true, true, true, true, true, true. They keep saying true all these times, all these notes. Let's say no. We're going to assume it's blank, it's true. So now we want to, so now we need to go through and figure out, we'll start with the pointers and then we can go through the other ones, right? So can c, is c structurally equivalent to c? Yes, it's always going to be structurally equivalent. Is c, and I'm actually going to erase these. I actually like the, right? So c is structurally equivalent to c? Is c structurally equivalent to d? What would need to happen for them to be structurally equivalent? It has to be structurally equivalent to b. Are int and b structurally equivalent? No. No. So this is a big old no. What about d, c and e? B would have to be structurally equivalent to i. C and e? No. Int would have to be structurally equivalent to a structure, so it can't be possible. Yeah. Then we do, let's see if it'd be e, c. d and d are obviously structurally equivalent. d and e, this would mean now that b and i have to be structurally equivalent. b is a string, i is a structure. Nope. Nope, that's not there. And that would be this one here. That's it. So that's it. So if I look at what's, so f, h and j, these are the structures. Okay. So I did all the pointers, right? The pointers are only structurally equivalent to themselves. Right. Now, I probably, what I was doing is, you know, I want to run through this one more time to make sure nothing changes. But I know everything is the only, you know, the equivalents, things are structurally equivalent to themselves, right? The diagonal is never going to change here. And everything else is false, so I've already proven that everything is not structurally equivalent. Okay. Let's look at f. f is structurally equivalent to f. f is structurally equivalent to g. No, why not? It's not in the same order. Not in the same order, right? This is testing, making sure you remember the way we did the structures, right? The order is the important thing. This is a string int. This is an int string. They are not structurally equivalent. So f and g not structurally equivalent. f and h is a string equivalent to a point or to an i? No. No. Can't possibly be. So not structurally equivalent. f and i. So string and e will depend is, can string and e be structurally equivalent? What? E is a point or to i, so no, that can't be structurally equivalent. Can f be structurally equivalent to j? No. F string pointer, no. No. G to k. F k. String pointer, no. Then we do gg structurally equivalent, gh int pointer to int, no. G i. No. E int work. E is a pointer to i? No. So no. K, j. G, gj. No. Int pointer, no. It's cute. Plus two. Int pointer. No. No. All right, h, h, definitely structurally equivalent. H i. Yes. I. Okay, pointer to i and an e. E is a pointer to i. Yeah. And i structurally equivalent to i. So that's structurally equivalent. Then we have to look at the next field, right? We can't just look at one field. That's every single field. Is d structurally equivalent to a pointer to a string? Yes. Yes. So d is a pointer to a v. So it's a pointer, that's good. So the pointers have to point to the same thing. This is a string. This is a v. v is structurally equivalent to a string. And the order is the same. And the order is the same, exactly. I. I is good. H j. So h is a pointer to an i. j is a pointer to a k. I and k are they structurally equivalent? No. From the table? Yes. They are structurally equivalent, right? I and k. All right. Then we look at d. You say, is d structurally equivalent to a function that takes in kc and returns boolean? No. No, right? It's a pointer to a v. So this is not structurally equivalent to h and j. Okay. So we have h and k. We have h, we have k, pointer to i, pointer to j. Is i structurally equivalent to j? Yes. The table says yes. Okay. That's good. But is d structurally equivalent to j pointer to int? No. No. d is a pointer to a v, so that can't possibly be. So hk, not. Okay. i. i is structurally equivalent to i. ij. k is e structurally equivalent to a pointer to k for now. So e is a pointer to i. So i and k are they structurally equivalent? For now, we think they are. Yes, for now they are. Okay. Okay. But then we look at the second parameter, the second field, right? We see pointer to a string and we see a function. Functions and pointers can't be the same type, right? So this is definitely not. Okay. ik. Here, x is an e. So we say is e the same as a pointer to a j? E is a pointer to an i, so are i and j structurally equivalent? i and j? No, they're not structurally equivalent, right? We've already decided that. This means ik cannot be structurally equivalent, right? And it also helps if we look at the second parameter here. The second field, sorry. Okay, so ik. Alright, so jk. j is a pointer to a k. k is a pointer to a j. Are j and k structurally equivalent? We don't know either. Yes. Yes, morning of the table, yes. That's why we fill in the table first. We first have a check mark. Then we say, okay, the second field. Are they both functions? Yes. So for them to be structurally equivalent, every parameter must be structurally equivalent and the return value must be structurally equivalent. So we can easily see return value check. So we see, is k structurally equivalent to j? Yes. So far, yes. Is c structurally equivalent to a pointer to an i? Yes. Yes. Yes. So they're structurally equivalent. Look at that. Yes. If we were looking at j on her decay, why did we know already that the pointer became a pointer to j? We looked at which one? Say it again. So we're looking at the j decay one. Yes. So why did we say that we knew that the pointer decay and the pointer j were the same? Because that is how we do a structurally equivalent algorithm. We assume from the start, so there's two ways to do it, right? We assume from the start that they're all structurally equivalent and then we prove structurally non-equivalent, right? The other way to do it is you start as they're all non-equivalent and then you go through and prove that they're equivalent. The problem there is you get the loops. So here we break those loops by saying, okay, we assume that they're structurally equivalent until we have evidence to prove otherwise. To say it's time of the test, would you just, like, bar truth? The ones that you assume were, like, structurally equivalent because of the table being proved from the start? Like, would you mark those just so, like, you don't have to go through all the structures again? You know what I mean? Say that again? So, like, j and k. You assume that j and k were equal and that's how you figure out their equivalent, right? Would you, like, put a mark, like, let's say it was actually g and h that did that for it? Just put a mark next to them just so you know so that you can just go through again and check. I would, so on a table like this, what I would do is I would go through one more time checking all of the non-empty tables, right? So I've already proved, if I've proved that they're not structurally equivalent, then I don't have to do any more work. So you just recheck the true ones? Exactly. I don't have to recheck the true ones and I don't need to recheck the diagonals. They're always going to be true. So here I'd check h, i just to make sure nothing changed. And I'd say yes, h and i are structurally equivalent. And I'd also check j, k again one more time. So now I can answer the question so I can say, okay, what's structurally equivalent to f? The only thing structurally equivalent to f is f. h, what's structurally equivalent to h? h and i. What's structurally equivalent to j? j and k. j, k, guys. Okay. So now we've got that all out of the way. Now we have another question here. Yes? I'm sorry, someone already asked, but do we have to write both itself and the other thing? What is just the other thing? Yes, write the, write itself, right? It is structurally equivalent to itself. Okay. Variable. Okay. So here we have w and x are strings, y and z are v and d, p and q are ray of j's, r's are ray of j's, s is a function that takes in the j, returns in it, t is a j. So for each of the following assignment statements, indicate if the statement is valid under name equivalents, structural equivalents, or internal name equivalents. So we're going to write one for name equivalents, two structural equivalents, three internal name equivalents, or four otherwise, right? So this would be, this is telling you how to write that there is a type error. Contrast that with the first problem. Okay. Write all that apply. So can I do q is equal to r? Yes. Array of j under name equivalents. No. No. Can I do it under structural equivalents? Yes. Yes, the structural equivalent. The internal name equivalent. No. Okay. pq, are pq internal name equivalent? No. No, it has no name, right? This is an anonymous type. This type has no name, right? This type b has a name. The type name is b, right? And like here, the type name is d, even though d is a pointer to a b, right? It still has a name. The name is d. Okay, pq. So is it structural equivalent? Yes. Yes, are they internal name equivalent? Yes. x equals y. So x equals y, string and b, are they name equivalent? No, they do not have this name, right? One is a string and the other's name is b, right? Are they structurally equivalent? Yeah. Do they have internal name equivalents? No. Right, because here's a string and here's a b. They have different names, right? Okay. z equals q bracket zero, right? So what is q bracket zero going to? What type is going to be returned? J. J. So this is asking, is j equivalent to the type of z, which is a pointer to b? Which is a d. So j is a structure. d is a pointer, right? So is it name equivalent? No. No, no, no. It's a type error. Okay. Q's, so we said array access of q returns j. And then we have s. So s takes in a j and returns what? An int. And then we use an int inside of an array access for p, which returns a j. So ultimately this returns a j. It looks like crappy j. Okay. And then t is what? The j. So are they name equivalent? Yes. Yes, they have the same name, right? Both are type j. Yes, name equivalent? Are they structurally equivalent? Yes. Are they eternal name equivalent? Yes. Wx. So w equals x, are they name equivalent? W and x. Yes. They're both strings, right? Yes. Definitely the same name and they're the same structure and they're the same internal name. Questions? Yes. Why is string name equivalent? What's the name of it? Isn't that the primitive? It's a primitive type, right? But it's not a new type, right? So these pointers and structures, these arrays are creating new types, right? So here we have a string. A string is a string. It's a string, right? That's the name. It's built in. You don't have to worry. It's already predefined for you. Yeah. So is that why P and Q aren't the same equivalent? Because you don't know if they're the same size array? It's more about the fact that we don't have a name for it, so they're not name equivalent. It's just name equivalent. Because it's like a new anonymous type. Oh. It's just about the names. Yeah. Because here, I mean I guess it does depend on how you're doing size or something, maybe. You can think of it that way. But it'd be the same thing like defining here's a function. The type of this function has no name, right? We don't know what the name of this function is, right? It's not like we're saying every function that has this type is a type foo or something like we declared over here. We know its type is a name. We just don't know its function. Name. We don't know the name. So the only way you have something name equivalent to s is if you have like s comma y and then takes the definition of what it does. For where? Here? For s. For s? Yes. You would have to define like it. So here we've declared types, right? Now when we use d, every time we declare a variable that is name d, right? Those are going to be name equivalent because it's literally the same name. Because we have defined the name as d. Here we have not defined any name for these functions so they can't name equivalent. Exactly. No. Internal name equivalence is about where it's declared here. So this internal name equivalence means that internally it's going to give the same name. Wait. I see. I think you're right. Yes. Yes. If they're name equivalent. Let's see. X, Y. They're both pointing to shrines. Wait, no, no. They have different names so they don't have the same internal name. Okay, yeah. That's what we think about it, right? They don't have the same name and they're not declared. So here, p and q, right? We don't know what the name of their type is but we know they both are whatever this thing is. So internally those are going to be the same. p and q are going to be the same. It's about what variables are declared together on the same line. So essentially they'd be both, they would both be pointing at the same box circle diagram. It's more about types though. It's more like when you built your type system, right? And you gave, you said all of these things are this type, right? You have that constraint. This is saying p and q are both this type, whatever it is, we don't know the name, but internally we know they have to be the same because they're declared on the same line. Here you'd have to do, essentially you have to think about it. You have to do more work to see that this array of J that R is the same type as p, right? You have to do more work to look at the types and see if they're the same. They don't have the name, yeah. Because p and q, what's the name of the type of p and q? Right, well how does p have a name? Now when t equals p and all of that, how does that have a name? But the type that's returned is J, right? J is the name. Why is it returned there? Because it has all of this stuff after. What's the difference? Between this, p and p0. What's the type of this? Yes, exactly. And what's the type of this here? After applying the array access operator, right? What's the type of this here that this returns? The whole thing, though. What is this return after accessing it? We don't know. We don't know. That's in p. Right, p is an array of Js. Exactly, perfect. Then if I index it into that array, what is an element of an array of Js? Whatever J is. If I said A is equal to this, let's say you're doing Hindley Milner, right? What would be the type of A here? It's a J. So the array index, right? We have an array of Js. The index operator is going to pull one of those Js out and return it. So the type of whatever it turns is kind of like, it's just like pointers, right? So when you dereference a pointer, you get to the type of that dereference is whatever that thing points to. That's a good question. It's kind of not intuitive. Yes. So, you know how Q and R are not having internal name equivalents? Correct. So pretty much, they don't have to be on the same line. They have to, yes. They have to be on the same line. Yes. I'm confused why W and X have name equivalents, but we're saying that P and Q don't. So, what's the name of this type here? Anonymous. Anonymous. So it has no name. Okay. Right? What's the name of this type here? That's a string. It's a type that is built in. It's already named, right? String. Any two strings are going to have name equivalents, right? Just like any two integers are name equivalent because the type of those is int. But if I define a new type like centimeters, which is an int, I don't want to be able to equate centimeters to ints because it's not the same thing. They don't want the internal same name even though they may have the same size storage, right? They may be ints underneath, but the programmer has declared a new type that says these have to be ints, or these have to be, these are different names. Okay. Let's move on to the next question. All right. Consider the following code in C syntax. Draw the program stack at the first execution. Yes? Yes. What else would it be? I mean, so the basic types, right? I mean, I guess, I do agree we never defined it specifically, right? But like string, int, Boolean, right? Those are the names of the built-in types, right? Right. But like a pointer to an int is now a new type that never existed before, and an array of ints is now a new type that never existed before. The same x is an int, and y is an int. Yes. The same int is the name, right? They have the same name. All right. So, draw the program stack in the first execution of location one, label on the stack all function frames, and inside each function frame label the parameters to the function, the values of those parameters, the function's local variables, and the value of those local variables. Okay. Also important point here. You do not need to follow precise C-deckville calling convention, so we're not going to be creating, or we don't care about the order of the local variables specifically. We just want to make sure that you know how to draw and understand the stack. Also important point, right? Assume static scoping and pass-by-value semantics. This tells you exactly how to interpret the C program. Okay. So, we have main. So, we know here we're going to have our function frame for main, and it's going to be passed, it has some x. What's the value of x? We don't know yet, right? When main gets called, there's no value for x. It has a local variable pop, and a character array of a's. So, I'm going to kind of represent it like this. You could also spread it out and do a0, a1, a2 with the value specifically of each, and that would be totally fine. Okay. Let me set check. Here we have global i is 10, right? Do I draw that on my stack? No, right? i is not on the stack. The stack is just the function frame. I need to keep track of this i so I know what happens, right? Okay. So, if i is 10, i... Is i 10? When main is first executed? Yes. We set x equal to 20. We set i equal to zero. We then print out the values of x and i. Do I ask you to print what it is? I guess not. Well, that's probably debugging stuff for me. Okay. So, print out the values. We know exactly what they would print out. It's actually very easy if they set it right here. So, if x is greater than zero, so it is x greater than zero. Yes. Yes. We're going to call function foo, right? So, we're going to have a new frame on our stack. We're going to call this frame foo, and actually we're not going to... I'm going to do kind of an open-ended one so we can add more, right? So, we're passing in, right? foo has the parameters b, the parameter c, and the parameter a, right? Now we have to look at... So, when we invoke this function, what are the values that we're passing in here? So, if we're b, we pass in a2. Zero, one, two is two. a0, zero, and x, which is 20. So, that's just the parameters to foo, right? Then the local variables of foo. foo has two local variables, i and t, right? So, we say i is equal to a plus one. a is 20. So, i is 21. Now we're calling what? Can we do that? Function. No. No? You can. It's a function, right? You can, yeah. It's a function. Yes. There's nothing special about me. Just a function just like every other function. Okay. But, do we... So, what's the next function frame that's going to be on here? Is it going to be main, right? First, we're calling bar and passing the result of bar into main. Right? So, then we have to call bar. And bar has a beta and an alpha. I think this is from the last 6 a.m. From the last final? Last final. Which is 2 and a half hours. I think it's 2.50. So, we won't have questions this long. You won't? No. That gesture is not spot on. Yeah. A lot of the power of midterm comes from practicing and preparing for it rather than actually taking it. Okay. So, we call bar and we're passing A and C. A is 20. C is 0. And it has local variable B. B is 10. I think bar is going to go away, but that's fine. We still have to see what it returns. We have I is equal to I minus 20. So, I is the global I, which was 0. Now, it's minus 20. Okay. And then we return what? Main of I. Main of I. It's good. Oh, this is good. It's almost done. Okay. Ain't different than any program. Did you guys write? I've seen some of those programs. I'm just kidding. They're all pretty. I love them. All right. Return main of I. So, we pass in I for X now in main. So, now we have a new function frame main. We have X is the parameter which is passing in the global I as an X, which is negative 20. This part? Yeah. And then main has a local variable pop and the local character array. We have our array. And it is 0, 1 and 2. Is I equal to 10? No. Is X greater than 0? No. No. X is negative 20? Okay. No. Else what? Location 1. Location 1. So, now we're done. Now we have main, which is called foo, which is called bar, which is called main. Yes. The order, right? I mean, this is the order that these functions are called. Right? That's what this stack represents. That's actually one of the key ideas of function frames that I want you to understand. Don't put it on scratch paper. We can write it like that. We don't have to do like... It doesn't have to be continuous. Okay. Like we did in class. These don't have to be continuous. They do... You have to have every frame with the label. Right? You have to have all the parameters, all the local variables, and their values that you need. Right? Can you scroll down for a second? Other questions? Yes. Are you liable to ask if something like assumed dynamic scoping passed by reference? Why not? Okay. Okay. Are you ready to test? I'm not ready to test. Why are you looking at it? It's fun, guys. It's fun. Is there all fun stuff? Okay. So I'll let you guys decide. I'll just keep going. If you've got to leave, leave. I'll just keep recording. Do you want problem four first or problem five first? Four. Five. Four. Five. Five. Five. Five. Five. Five. Five. Five. Five. Five. Five. Yeah. Okay, we'll do five. We'll go back and do four. Okay. Okay. Okay. Problem five. Fully emphasize the following land expressions. Another way this could be phrased is fully disambiguate these expressions. Right? So it's starting like in this inner one, is U p is disambiguous? Just this figure? No. Right? But WXUP, right, is ambiguous. And so we know this is going to be left associative, right? So we're going to add parentheses around WX. And then parentheses around WX, probably the changes. So if you say rewrite this, this gets crazy. OK. Here, right? We're allowed to rewrite it. Would we be allowed to change a parentheses or already there? No, because that would change the meaning, right? So I've also added, right, I know that this period means that everything inside here, right, to as far right as possible is inside the body of the lambda Y abstraction, right? So then I also know that this body extends all the way here. And then what do I know about the WY, the WX, and this? Right, yeah, we need another parentheses around this. So it would be lambda X dot XY lambda Y dot WX. Yeah, well, that's what I do. I'm not going to see an alley. And you could do it yourselves, right? That's probably the point of doing a practice mentor. We have parentheses around the whole body of X. We have parentheses around XY, because XY applied to this is ambiguous, right? So we need to know that XY happens first. And the result of that is applied to this. You missed the parentheses after the, and there should be four. There should be four, yeah. How long y'all want to be here? All day, all day. I like that. All day for the grade. Well, this is more valuable than that. Absolutely. Don't tell your other professors. OK. Oh, this one and this one. Got it. Exactly, there you go. So I kind of want to see if you can figure it out. It's like a 1,000. OK. Right, so the next one. So this whole thing is within the body of Z. Oh, you're missing a part again. You're missing a parentheses. Yeah, you are missing one. Oh, another thing that I can do that you can't do is zoom in. Yes. OK, so I know I'm going to have to have parentheses around this whole thing, because this is the entire body of Z. I will then, so this is, so we go next. This applied to this. Is there any ambiguity here with the existing parentheses? No, right? It's two things being applied to each other. So that's all that it can be. Adding parentheses won't clarify anything here. Inside the lambda y abstraction, we have, where does this end? Here or here? At the first parentheses. At the very right. Here? Or here? No. No. It's in parentheses. Exactly, yes, it's in parentheses, right? So you think about parsing this thing. You think about parsing this thing. There's no possible way that this period can't extend past this, because this parentheses means that this is going to be one unit, right? When we parse this, everything in this parentheses, we can't extend and try to parse other things, right? It's going to change the meaning. Is Z y Z ambiguous? Yes. Yeah, so we're going to throw some parentheses around there. We go over here, lambda x, so we can add parentheses from here to the end of the body there. And yeah, you could maybe throw some parentheses around x, but I don't think it's going to be so. Yeah. I'm curious, do you need those parentheses? Yeah. Which ones? The last one you just added. Yeah, I guess I would say no, because it should be unambiguous, because it's just one expression following it. I would be fine. I mean, you don't have to go super crazy, but it needs to be financially the same, right? So what you're looking for is, A, is it the same meaning as what it was before? And B, is it in any way ambiguous? But I think before you write it would be a not. There'd be no ambiguity without having these, but to me it makes it a little bit clearer. OK, we'll get A, B, C, lambda x dot x, A, B. So here I need parentheses around A and B. I need more parentheses around left associative. And then, so now I don't need any more parentheses. Well, but I need to understand exactly what this expression does. So yeah, I would throw parentheses around this just to make it very clear. Then I would add parentheses around the body here. And then more parentheses around x, A. It's actually a lot easier. Questions? I thought was really useful being these. Is it writing it out how we wrote it out with the context for grammar and parsing it fully? It would really, really help to understand what was going on. Yeah, so like a parse tree? Yeah. That would be really good. That's actually a great way to practice too, so that way. I can just look at this and kind of know where things should go, right, but it's all about knowing why these things are like this and why they're parsed like that. So yeah, you have the grammar for it, so parsing it is really good. OK, circle all three variables in each of the following expressions. I wonder if I can get the people at home sick. Yeah. Circle all three variables in each of the following expressions. So here I have lambda w dot twi. So inside the body of lambda w, what is not free? What is bound? W. So this means what about t and i? They're free. They're free. Now, w is outside the body, so it is now free. Lambda i, so inside the body, i will be bound. And remember, because of the disambiguation rules, we know the body is this entire thing. I don't have to parenthesize it if I was going to do something like this. So inside here, i is now bound. Inside here, w is now bound. So which of these three is a free variable? Similar logic, inside here, w is bound. So both t and i are free variables. Inside here, i is bound. And then inside here, w is bound, which means t is free. But outside here, w is no longer bound, so it is now free. Actually, I have really pretty letters when we zoom in. Yeah, it's cool. I wish I could write this too. So here it may help to put the parenthesis in. Here, i is bound, t is bound, i is bound again. No escape. So i is bound. It's bound to this i, right? We didn't want to talk about it, but it's bound to this abstraction, not the outer abstraction. Now here we have another function where we bind w. And so now we have itw. All bound. All bound. So we would call this a combinator because there's no free variables. OK. Problem five? Or four? Yeah. OK. Consider the following code in C syntax. Parenthesis, use static scoping. Include standard IO.h, so let's skip the actual code. And let's look at the question. So if parameters are passed by value, the output of this program is. If parameters are passed by reference, the output of this program is. The next one, and this is problem four, continue. Is this useful, do you think? Repeating? Yeah, it's very useful. If parameters are passed by name, the output of this program is this. Yes. OK. Let's see. Common mistakes that I saw before we start on this problem. So here this printf, what is this going to output? What is it actually going to output? Number dash a number, and then a line break. Yes. The dash, I mean, I honestly don't care if it's a dash or a space. I mean, you should have a dash because it's a dash, right? If I just did new lines, it would be a little bit ridiculous, the output, right? It'd be like 30 things output. So that's why I added dashes, because space is actually hard to visually see, right? So you may not know that that's actually a space. This does not mean that we're subtracting v from star c. Important to understand. And it's a thing without any problem. It was. OK. So why don't we go through this normally, right? And our normal pass-by value, this question should be the giving, how I put the points here, it's fine. This should be just go through this, execute this. How would this C program execute, right? OK, we don't have any global variables, which is nice. We have main. So main has an int i. So I'm actually going to draw the stack just a little bit, just because it helps. i is 10, t is going to be alpha, right? It's going to contain, let's say, alpha, which is some memory location. Maybe box circles better here, but yeah. All right, yeah, actually that's good idea. So we have i, which is 10, we have t, which now has the value alpha. And then we say star t is equal to 20. So I'm copying the value 20 into where t points to 20. Then I'm calling bar it. So then I call bar, and bar has parameter b. So what's inside b? The value 10, exactly. And then c contains alpha, yes, exactly. But the important thing here is that there are new boxes and circles, right? And then a also has an array. So technically, a would be a pointer. I think we can consider it like this right now. And this would be fine. Where's a? OK, yeah, we just changed it either. OK, great. OK, a is that. Then we have an x in bar, where x is 0. Then we set b equal to x. What does that do out here? Nothing. Exactly. b equals x, so 0. We see we're doing malloc size of int. So c, we malloc a new beta. And we copy that value into here. And I set star c equal to 42. So I'm going to change beta to now be 42. Then I'm going to pass into foo x and a bracket x into foo, which is just the value. Which is just the value. So here in foo, I'm going to have b, which is 0. And I'm going to have c, which is, OK, so ax. So a is this array. x is 0, so it's going to be 0 as well. Then I have a local variable x that says x is b plus c, which is 0. And b is equal to b plus 1. Return x plus c, 0. x plus c, 0. So I come back to foo, and I put 0 into a2. Then now I print out, OK, let's b is 0. Star c is 42, right? 0 42, which would be 0 dash 42. Then I'm going to print out all the a's with dashes, right? So 0 1 0. Then bar returns, we come back to main. We print out the value of i and the value of star t. i is what? Then star t is 20. OK. Now if the parameters are passed by reference, now let's see how to start. OK, this is 10 minutes. OK. The parameters are passed by reference. The output of this program is, we have main. We set i equal to 10. We malloc a new t. We set star t equal to 20, right? So same all here. Then we call bar of i t. But now when we call that, now how does b and c in our diagram here change? b points to i's location, and c points to t's location. Yes, right? The key is just the bindings here, right? So b is now bound here, c is now bound here, right? That's what changes. We still have the local a, which is 0 1 2. Then we have x is 0. Now when we do c is equal to malloc size of int. Now we create our b, our beta. And we copy beta here. Then we set star c to b 42. We are now changing here beta, right? What happened to alpha? It's not a garbage, right? We can't actually access it, yes. OK, we did that. Then we set foo x ax. So now we pass into foo, right? Now we have x, c, and b, right? So x is the local variable. Let's not worry about that now. We have b and c. So what is b bound to? Is it x? b is now, this b is now bound to x. And then what is c bound to? a2. a2, yeah. So it's going to be bound to this guy, right? Yes. I think we slip to b equals x from the last function. Oh, we could call. OK. Yes, we did. OK, b equals x, we'll copy 10 into x. This b, this is b, right? Which is 10. We copy that into x, the local x, which is now 10. c bound to a0. x equals 0, b equals 0, b equals x. Sorry, we say x equals 0, this sets this to 0. Then you set b to x. Someone has not had their warning code. No, it's only one code. So sad. Is there somebody there? Let's wait and check. All right, so we put 0 into this b, good catch. Then we are, OK, so let me call this function. OK, we bind the local b in food to the same box as x. And we bind c to a0. a0, yes. OK, now we set x is equal to b plus c. b is 0, c is 0, which means x is now 0. Sorry, this is actually the local x, right? We have to make a new copy. It's good enough. Is that a statement or something? Yeah. All right, b is equal to b plus 1. We said b is 0, so we said b equal to b plus 1. We're going to return x plus c. We're going to x is 0, c is 0, so we return 0. So we set a2, that's where I got the a2 from, got it. a2, we're going to set that to be 0. And now we print out b star c. We print out what? 0? 0, 42? And then when we print out 0, 1, 0. Now when we return, now we return here. Yeah, and now we print out i and star t. What's i? 0. And star t is 42. So why did this other one change? Why did the first two outputs change? So local array with n bar. Yeah, we look here, b is the only thing that's, well, assigned to here in foo, which means that x is the only thing that could change, but we don't output x here. OK, are we good on that? We'll do pass by name through here. You want the answer, and then? Yeah, yes, yeah. We're going to do that, OK. OK, let's see. So i is 10 here. 10 t is, it's going to be the same. The first one, 0, 42, should be the same. Well, OK, let's step through this. All right, i is 10. t is maloc-ing a new thing. We're setting star t to be 20. We call bar, so we're passing in. So every time we see bar and c, we're going to use int. But these aren't expressions, right? So this isn't going to, it'll be fundamentally the same as pass by reference in terms of b and c. The difference comes in, we have x. We set b equal to x, so x, b is now 0. So b, this sets this i to be 0. The c malocs a new size of int. C is the same thing as t. So this sets this t to be basically beta. We set star c to be 42, which is actually star t equals 42. So now star t is equal to 42. Now we say bar i, sorry, where is it? Now we're here, we say a2 is equal to foo xax. So if we have a2, we're passing in, x right now is 0, right? But we don't pass these values in, right? We're going to make a new copy of foo, which is the same, except we're doing int x equals, let's call it x bar, right? Because it's bar is x, and then a of x bar, right? So we do this, and then we say bx bar is equal to x bar plus 1. And then we return x plus a bracket x bar. So this is going to be x bar is 0. So it's going to be 0 plus, why is this not a plus? 0 plus a x bar, so it's going to still be 0. So this x is 0, right? We have x bar is equal to x bar plus 1. So x is now 1, right? And then we return x, which is 0, plus a bracket bar. A bar is now what? 1. 1, so a1 is 1, so it's going to return 1. So it's going to set a2 to be 1. And so when it outputs b, right, it will still output 0. Star c is going to be 42. Then it's going to output 0, 1, 1, right? x is 0 here, 0 plus 1, 1, okay? Yes, okay. And then this will return. Then we print out the values of i and star t. i is 0, star t is 42. So the big change is in the second line, right? But it is actually a pretty significant change that shows that you know exactly how a call by name works.