 So these are the grades from Project 3, sorted by score, right? It just doesn't reveal the information about whose score it is. So let's see, we had, actually pretty impressive, we had 69 people who got 105%, so we completed it 100%. Let's see, 85 people got 100 or above, that's also super impressive. Let's see, the A's, it's about 109, that's also pretty cool. Let's see, overall, let's see, overall the average is 69%, it's just 70%, that's actually 10% higher than I think it was last year, it's a little bit difficult because in the final grade book there's zeros from people who didn't even submit some, this is just the people who actually submitted. Yeah, so the average about the zeros is 74%, which is definitely higher than the average about zeros from last year. Unless it's due to a huge cheating scandal which we'll soon uncover, very good work, I'm really impressed with how you did it. I think three is hard, I definitely know that. Cool, questions? You ran all the code through the comparison engine thing, right? Not yet. It's coming. So your scores as a group can only decrease from here on out, I guess. You didn't set the server up to do that automatically? Not yet. You can tell most of them to do that. Cool, any other questions? Project upgrades? The other thing, you all should have got the email, but just to reiterate, I'm not going to go over it in a ton. Project 4 is released. I sent out an email to the mailing list. Do 11, 7, 16. It's actually a very cool project. You have two parts you need to finish in incomplete parsers. You need to be part of the parser, you need to finish the parser using the grammar, which is something that you know how to do. Then you need to actually type check that grammar according to the type rules in this document. We're not going to go over it in class, that's all going to happen in the recitation section, so please go to recitation sections. You can understand the project, understand what's going on. Cool, questions? High-level questions? Project 4. I'm not going to take this as long. It depends. I don't know. Some people say it's easier, some people say it's harder. I think that's all. I really feel it's kind of random. It kind of depends. If you got stuck on some weird error in project 3 that took you two days to debug, and that doesn't happen to you on project 4, you'd say project 4 was easier. Whereas if the reverse happens, then you'd say project 3 is easier. Does one have unit test and submission server? Yep. So do we need any project 3 or 4? No, it's a completely independent project. So we'll give you some incomplete parser on the submission website to be able to download that and start from there. The projects are all distinct. I guess I should also say for those of you who didn't do great on project 3, don't lose heart. I've seen people pass this class with not great grades and even zeros on project 3. I think if you do the math, you'll pass if you knock project 4 and project 5 out of the park and do all the midterms and final. So don't always hope, but that should re-energize you to re-dedicate yourself to projects 4 and project 5. So some advice from people who came from office hours about project 3, start early, submit early, and submit often, because I don't care if it works 100% on your laptop, or if it's on a server. So you should as soon as you get to a state where you can test it, you should submit your code to the server to see what it says. So you can work out any discrepancies there. And just like on project 3, the test cases that we give you are on the server as well. So when you can get to a point where you're passing one test case at least, you should submit that to make sure that the server is executing exactly what you think. Yes? No. The test cases are being hidden so that we can submit them in the future. Project 4, good. Now back to types. Okay, so we started on Wednesday. We started talking about type systems, and we kind of had a discussion about the pros and cons of type systems, although it was a lot more on the pro part of type systems. You seem to be militarily in favor of type systems, not so much on the cons on what the drawbacks are of having either static type system or reactive player types. So what would be some of the cons of a type system? From your personal experience, you've been coding, right? You're like, only a stupid type system wasn't here. I can do what I want with you. Trying to overload operators? Can you expand on that a little bit? Yeah, so dealing with you have to do a lot of sometimes back bending to work with the type system depending on what you want to do. You used to, Java used to be really annoying with lists before they had generics in Java. Each Java was just a list, each Java list was a list of like objects. And so when you put objects into it, you're going to cast it through an object. And then when you pulled items out of a list, you had to explicitly cast it to an object. So you're actually, just by using this list, you're kind of getting rid of type safety. And you have to remember what types of objects are in which lists, do it explicitly as a programmer. And so really the type system is restricting what we can do. So sometimes I can actually feel restricting like compilers are really stupid. You should figure out what I mean here. It's not that hard. We may feel like we're doing extra work. But rather, at every single variable in our program, what the exact type of that variable is. When there's sometimes, as humans, we look at it and go, it's very clear that this is an integer. I'm assigning it to zero. That zero is an int. There should be an int too. But we like the safety. That was what we talked about. We like that. It's kind of like our security one. If we know that the program compiles, we know that we don't have any, we don't have any catastrophic errors. We have some idea that things are correct. Of course, we all know that that's not really true. We have to actually run it to see if things are correct. So the type system, we'll talk about it first informally, and then we'll talk about it and try to study it more formally. So really, the type just specifies a set of values. So int type means that the type of that variable compiles all numbers from, depending on if it's signed or unsigned, let's call it unsigned, from zero to two to 32. That is the set of values that that variable can hold. And we define operations on those values. So we know how to add and what that means on an integer. Cool. So we can associate type to do the variables or constants. And when we think about type, we think about just numeric types. We think about integers, doubles, floats. Longs. But there's other types. So the types of functions. When we talk about function signatures, how you tell between two different functions, that signature for a function is essentially its type. So what's the return type of the function? How many parameters does it take? What are the types of each of its parameters? So for a type system, you must have basic types. These are handed to you from the programming language designer. In C, we have integers, floats, doubles, other stuff. These are the basic types. Can you change these? Can you add more because do you feel like it? Guess how? We think C. A struct. What is a struct doing? Defining a structure. Why are you defining a structure? You're defining what? A collection of different types. You're defining a collection of different types and you're calling it something else. So really you can think about a structure definition as being able to create new types from the basic types or other structures that you define. So really, a type system has three things. You have basic types and you have new types and you have new types. You have type constructors. How do I make new types? What about pointers? Is an int the same thing as an int star? Is there a limit to how many stars you could do? You could have a 10 star pointer. So this isn't defined in advance. You are creating new types whenever you use when you're creating a new pointer type. Why is that useful to us as programmers? Why do we want to be able to create new types? Why do you stress? Do you have to stress? Make things more abstract in what way? It's specifically saying that this question of data should be associated in some way. So instead of talking about let's think about coordinate points like an x and a y and we'll think about only integers for now. So I have two variables int x and int y to treat them independently and say they represent some point in my 2D space. But if I create a structure and I call it structure I'm creating a new type called a point that has an int x and an int y Now I'm thinking of those types at a higher level I'm not thinking about the individual x and ys I can define operations on points I can say what happens if you multiply one point by another or add two points and ask create a function to calculate the difference between two points So really that raises my level of thinking about the program of one because I don't have to think about the raw x and y values I'm giving them an abstract name and calling them that collection of a point So we may want to maybe model the problem domain that we're talking about We can still model it without creating structures or grouping types together But it makes our model more closer and makes it present more closely to the problem we're trying to study In a similar way think about the function that So what's the difference So let's go to here Is this working? Let's go here There we go What's the difference between this? Let's say we want point in x in y So here I'm defining a new structure So think about this semantically You as a programmer, what's better to do create a function called add that takes in a function like this or to create a function like this What's the difference here? So under the covers, what's going to happen? Is there any difference? No, right? It doesn't care that we're talking about types or that we're talking about structs The computer cares, I just need to add numbers together and do whatever operators you tell me to do But which one of these is maybe the better way to do things and why? The first one, why? Because I did it first Less typing? Why is it more abstract? So it's a couple different ways to think about it One way to think about it would be to somebody who's going to call this function We may be writing this add function that's not going to be used by us often times when we program especially outside in our careers The things, the functions that we write have to be used by somebody else So here it's very clear I'm adding two points together It should be very difficult for somebody to pass in different ints to this function and to get some unexpected results Whereas in this I can call this function and not even worry about points I can just think maybe this function adds four integers together But really that's not what it does but I can have an int that maybe represents centimeters or something What would be the return value because functions can only have one that I know of The first function can return a struct point something like that So you can only return one value What would it be? Ints, yeah ints something like that You have to take it up a little bit from C Let's say it returns a scalar It does the distance calculation between two points So that would be easier in that case But yeah, you have to have a language that allows you to either return two values or return one value that's a tuple that contains multiple values But you are still using types like what happens is now you want to change your points to be in three dimensions So let's say you want a Z coordinate So now which way what are the pros and cons of each of these types of decorations What was that? The struct is less work I mean it's going to break things probably But we added in X Z here And then our function definition is still the same We may need to change the body to say what do we do with this new Z But here we have to append and change the function signature to add these new arguments So the type system is allowing us to describe our problem at a higher level and to describe the functions on our data at a high level I want a function that calculates the distance between two points This says I want a function to calculate the distance between four integers essentially So this is why type constructors are so important So we have basic types, we have type constructors We also can have a way to and we'll look at this later There may be a way that we can infer what the types are in the program And we'll see this, this is actually all of what project 4 is about The fourth thing is we need to be able to tell does this program type check right Are these types compatible So what times when does this come into play When do type compatibility come into play There are two types So what you're saying is A less than B You have a string and an integer that does not make sense because of the type system Type system says you can't compare to and into a string What are their cases? Comparing? Was that any binary operation? Yeah, what else? So less than, greater than is equal, double equal sign arithmetic operations bitwise operations What about assignment statements You ever got a type error to assign a variable to maybe another variable and it complains, and we talked about I think on Wednesday you just put the explicit cast and it goes away But that's because what you're trying to do violates the type compatibility rules of your type system So we're going to study each of these in turn and try to understand what these things kind of mean and as we go on we're going to introduce basically a language to define types and to do type checking and all these kinds of things So we all know we can declare new types So we have basic types that the program So that's included in the program language So remember this is now you have to step in from the programmer to the language designer You are designing C or awesome language What do you want as your basic types? What makes sense? And you think it may be something that's trivial So like in C how are strings usually represented in C an array So it's an array of characters that's null terminated So there's a zero at the end What's the size of each character in a C string? Each character is one byte Does that actually correspond to characters in languages? How many characters can you represent with one byte? 255 because you can't use zero because zero is the null terminator So you can represent 255 Let's look at ASCII table and we can see well it only shows it up to 177 but we can see all the the classic ASCII characters represented here Does this represent all possible characters that may watch the output in our program? Anybody speak any other languages? Do you see your other languages characters represented here? No kind of bummer, right? All of us are lucky that computers were invented basically in the US and so they got to define these standards So our thing always works and I feel your pain because when I sign up for conferences and stuff sometimes I make the mistake including the E with the accent mark on my name and then I go print my badge and there's nothing there to include the E or S is up and then actually drawing myself and as you can tell my handwriting is really bad for me so I've learned to not do that So we've invented other types of encoding like Unicode and Unicode what is the size of one character in Unicode? Does it correspond to one byte? For those that know Unicode? Anybody? You said So it's a variable bit so a variable byte I should say I believe Unicode has all the same as ASCII and then above that you can have multi bytes depending on what specific code point you're trying to say The point is this breaks the abstraction barrier between characters and bytes and when you're writing in C so the language designer made the choice back in the 70s when they were designing C to say that a byte is a character and a string is an array of characters that are null terminated which now in today's age does not make sense because now you have this separation between bytes and characters So newer programming languages actually do this separation in the type system itself You can have a string and you can loop over the characters in that string but that's maybe not necessarily going to be every byte of the string you may have to have different functions to turn that string abstraction into raw bytes that are encoded either Unicode or whatever encoded format It's actually one of the big reasons why I don't do a lot of Python 3 because I'm used to the Python 2 way of doing things where you don't have to worry about that but in 3 it's supposed to be a lot better but also can be more annoying Anyways, the point out of whole migration was this is decided by the language designer You cannot make new basic types But is that actually true? Let's say you wanted to make a new Anybody try to use when they're going to see trying to define a new Boolean type Did you know there's no Boolean types in C? So if you tried to define a new Boolean type how would you do that? A macro? So how would you do it? Do you pound death? Is it something like this? Maybe not without the semicolon I actually forget the exact syntax I'm trying to define true as 0 Wait, that's wrong Something like this So are you adding new types to C? What are you actually doing? What happens when these pound defines are seen by them? Does the compiler Does the compiler see these? What sees these? The pre-processor C has a step before the compiler that reads all of the pound defines goes through and does a literal text substitution to where everywhere it sees Boole it substitutes int and everywhere it sees true it substitutes 1 so that the compiler never sees that So can the compiler type check these? No Because it does not exist to the compiler The compiler only sees integers So you can fake it in C You can fake these pound defines but you're not actually creating a new type So your programming has to have basic types Then we need some way for us as programmers to construct new types We need to be able to define new types and what those types mean and how they're allowed to operate that is part of the type system So for our little toy languages what kind of type constructors do we have? So we can have pointers just like in C We can have a pointer to T where T is some type So we're creating a new type here So we're saying a new type if you start with a type you can always create a pointer to it by using pointer to T This is going to be the exact syntax pointer to some type So is this definition recursive? Is pointer to T a type? Then can T be a pointer to some other type? Can that T be a pointer to some other type? Can it be infinite? Good for your question You could have a circular dereference You could have pointers that But can you declare a type that is infinite? Right, so if we go back to our very first day our input to our compiler is a sequence of bytes Can you compile an infinite sequence of bytes? No, it doesn't make sense Your input to your program has to be finite So what does that tell you about the definition of this type when you're constructing this new type? Can it be finite or infinite? I don't know Finite Let's think about this some more I think it's going to come up later But fundamentally we can't have an infinite type or we don't want an infinite type You don't want a pointer to a pointer to a pointer to a pointer to a pointer That doesn't make sense We can define structures We're here We're saying A1 is a type So we have different fields in our structure A1, A2, all the way to AK and we have each different field in our structure has different types Now right here we're just talking about syntax So we're saying what are the ways that we can construct new types in this language We're not saying how do you create new types We're not saying what exactly or how to tell when these two types are the same So we'll see there's actually some choices we can make when we say our two structures are the same type When your TI is a previously defined type We can't have a type We can't have one of these subtypes in this structure refer to itself So is that true with languages that you're familiar with? Can you refer to the structure's type in the definition of a structure's type? Yes, no? When have you done it before? Yeah, that's how you do linked lists So let's see We'll just leave this jumping here So we're defining new struct foo So you're saying you can do bar like this So one problem is I didn't put a semicolon after here So why is it an error? You just told me I had to do this, you failed All of your grades get reduced by 10 That'd be crazy What was the problem? Star Star? So what do I actually want here? I want a pointer to the same type So I'm not using the same type And think about it In C if I have struct let's say int bar and int baz The compiler is saying Okay, I have a structure The way I'm going to do that is I'm going to reserve Whenever I see a variable type foo I'm going to reserve instead of 4 bytes for a regular integer I'm going to reserve 8 bytes And the first 4 bytes will be dedicated to bar And the second 4 bytes will be dedicated to baz And I will treat these as one unit Right? So here, if I try to then say Hey, structure foo has structure foo in it I have to save for the structure foo An infinite Because each one of them has to have their own structure foo in them And it's going to go forever But now when I change it to a pointer Well, let's verify that that actually works It works So why does this work? What's the difference? Pointers are 4 bytes It doesn't matter what I'm pointing to I know that it's 4 bytes So that's why I can use it in here But I can't use it by itself I can't say I can't say a struct foo I have to say a pointer to a struct foo And the same thing holds true for our language here We can't say that we have this struct of the same thing inside of it That doesn't make sense We can say that we have a pointer to it and that could be fine But we can't say that one of these fields is the type of the struct itself That makes sense? Cool We have arrays, which is nice Also, it's a little bit nicer than C because in C, arrays are basically just pointers So here we have a ray and we can actually specify the range So we can say the range can be either single or multi-dimensional We'll see examples of this in a second So we have functions So functions So we have just like we used to in C the types of functions taking K arguments here or K could be 0 It could be 0 arguments Type 1, type 2 So these are the types of the parameters and return some type T Now let's think about this Is this true of most primary languages that you're used to? Can you put any type T that a function can return? Yes, no, maybe you thought So how to think about this? The flip of this question Are there any types that you cannot return from a function in your normal programming language in C or C++? A structure or collection that's too big to fit up the call stack A structure? I think you can still do that and the compiler will figure it out and not put it Oh, well maybe like literally too big for the call stack Possibly If it's a function on some database we can't return the database we have to return a pointer to it Yeah, that's true I wonder, because I know you can pass in by value a really large thing You can pass in something really large but on x86 passing is done on the stack so that's fine On 64 passing is done in registers So you could try to pass in something that's bigger than a register and the compiler knows that because it knows the size of everything so it will change that size to put it somewhere else I think on the stack in that case I think it works this Oh no, so you're right So on x86 the return is in the EAX register which means it has a fixed size so it must know what to do when it's a too large of a thing It probably pushes it on the stack otherwise, possibly So let's think about this Is this a type, a pointer to some type T? Yeah Can you return pointers to types? Yeah Destruct Can you return a struct? Array is a type We don't really have that in CRC++ Can we return an array? Yeah But I just said here on this list can I return a function from CRC++ What's different about functions? Is a function a type? No I'm just saying that here's the type of one type is a function When I declare a function for instance here Here I'm declaring a function main and what is the type of that function in the parameters that we have there Well it would be nothing here which returns an int That is the type of main So is that a type? No, why not I just said it was a type We are constructing these types Each of these things defines how to construct a new type We construct pointers, structs, arrays and functions So when I say it returns T Can T include function types? Yes Can you do that in CRC++? Yeah, so you can kind of think of the proper way to say that Yeah, in CRC++ I bet you probably never used it But you can return pointers to functions from functions and also accept them as arguments and then call them Similar thing in this abstract language we are talking about here the type system here So we are saying functions can return functions Returning pointer to T No That's in C In C++ you return basically a pointer to a function But in this language we are talking about here we return a function The stuff you said was passing a function as a parameter is how we do multi-threading applications We take this function having a function be returned kind of implies that our code is freakishly self-modifying not only is the code controlling the execution flow but what the execution flow is because if you can have a pointer to a function and modify it like you were talking about you could dynamically change the code of the program We don't have to be dynamic code but that could be one way in some crazy languages In Ruby you can do crazy stuff I've seen if you ever want to read the Ruby on Rails source code you'll see that they dynamically construct with strings classes and methods and add methods to classes based on what you do That's pretty crazy The key thing is it's very difficult in C or C++ because we can't write local functions Let's think about some programming language where I can define a new function inside of some function and just return it just like any other variable JavaScript is a great example of this JavaScript you can do this I believe in Java you can use Python you can do this with lambdas this function may or may not have a name that also depends on the programming language Here the type of foo would be in our terminology it would be void int and I'm going to put brackets around it to be a little more clear The type of foo would be a function and returns a void int I'm going to change the syntax but it's fine for now let's change it So we want void takes in nothing and returns a function that takes in nothing and returns an int There we go a little more consistent with where we're going I'm representing the same ideas here So if then in main we could say well I don't think my type 6 won't have to allow it but I can have some variable let's call it equals foo and then I can call baz so what would the value of x be here zero so I have a function returning a function just totally fine just like I can pass in arguments to functions so we can just get a function without just a function name you can see no yes we specifically so you mean without brackets like this so what's the difference here so I'm returning the result of calling bar this would return zero because it would call bar first and then return the return of bar which is zero here I'm returning the function itself like this so now we have to update the return here so we have an int return an int so we have something like this so foo takes in void returns a function that takes in an int to return an int and then here we have to change it like this and so this would not type check because the compiler knows the type of baz is a function that takes in an integer and returns an integer but you're calling it without passing an integer so let's say I put 100 what's my output going to be 100 I have no idea is the short answer because I believe I'm trying to think I believe in every language where you can do this you never have to know the size of objects I literally don't think you can but I think you, I mean it definitely has a size which is you don't know about it cool, any other questions okay this is something that's very important it's going to come up a lot when we talk about type systems so here is here functions or what we call first class citizens just like every other type you can pass a function to a function you can return a function from a function you can assign a variable to a function just like every other thing so really it makes it simpler in some ways to think about because just like an integer that means there is no difference between integers and functions it's the same we're treating them exactly the same cool so we have function types so now we can alright so now we can actually use type constructors to do a couple things so we can declare some types here so here I'm declaring a type called centimeter which is the same as an integer so why is this important, why would I want to do this it may actually prevent errors I don't know if you remember I don't remember the exact name of it but there was a famous rocket that blew up I believe without anybody on it which is good because some people were using centimeters and some people were using inches and when they passed it for one module to the other it was just integers so they never translated that so the rocket ended up exploding because really, and it's again about it goes to abstraction I understand the computer, it's all integers underneath but not all integers are the same centimeters are not the same thing as inches even though they may be both represented as an int and so this is really the power of type constructors is it allows us to describe our problem and describe the actual types that we're using so that we can prevent errors like this of using an inch when we think we need a centimeter so cool I think that's it