Without much further ado, let's get started with programming in ML. What I really hope you'll do, as we start doing this, is let go of any programming or any programming language you already know. For now, treat ML as this totally new thing. If you prefer, don't even call it programming. We'll have plenty of time later to compare and contrast what we're going to do in ML to things that you already know. And I really think that if right now you try to take each thing that I write down and say, "Oh, that's kind of like this thing I know in Java or in Python," or in whatever, it's going to confuse you and make things more difficult. It may seem like I'm going really slowly, but focus on the words and the terms, and how we're thinking about stuff rather than trying to guess what the answer is going to be as we go. I'll usually have things open for us in advance, but since this is the first time I'm showing this to you, what I'm going to do now is open the Emacs editor. This is what it looks like right after I open it. Your colors may be different. I've chosen these colors because I think they'll record better and in fact, I'm going to switch the size here as well so that it will be easier for you to see. Now I'm just going to open any file I want. I'll usually have this predone, but again, I hit Control-X, Control-F and now I'm just passing in a pathname. This file doesn't actually exist yet, first.sml. We're always going to use sml for our file extensions. Hit return and now I have this blank file here. By the way, another simple thing you can do is, if you create the file ahead of time, you can literally take your mouse, at least under Windows, and drag the file on to Emacs and it will open. So, here I am, in a blank file, and the first thing I'll do is write a comment. So, "This is a comment. This is our first program." Comments, like in every programming language I'm familiar with, are just things that are ignored by anything, except humans, and in standard ML, we start our comments with a round parenthesis and then a star and we end them with a star and then a round parenthesis, and yes, you can nest comments inside of each other. That's just a comment. We haven't written any program yet. Let's write a one line program, val x = 34. This program is going to create a variable and is going to have that variable hold 34, and because 34 is something of type int, short for the English word integer, x will be a variable of type int. What we see here is we are creating a new variable using the val keyword. So val is a special word in the language that says, "I'm about to introduce a variable.". X is the variable name we chose. We could have chosen any thing there like y or foo or hello or Dan. Equals is part of the syntax of declaring a variable, and then here, between the equals and the semi-colon to end it, I've put an expression and the simplest kind of expression we have is just an integer constant. Let me do a second one. Let's create a variable y that has value 17. Now I'm going to save with Control-X, Control-S, and now this is a program. I didn't need a main. I didn't need a class. I didn't need a method. For today, for this video, a program is just a sequence of these variable bindings. Each of these is a binding. We have a sequence of them and that's our program. If I want to run this program, I'm going to use the standard ML REPL, the Read-Eval-Print Loop. We'll talk more about that in a couple of videos, but for now, let me just give you the basics of how you run this program. I'm going to try Control-C, Control-S, then hit return. That brings up this other window, where I can now say, use, and then first.sml. So the name of my file, inside of quotation marks, to make it a string, this function, although think of it as a command use, then a semi-colon and then hit return. Sure enough, I get a message that it's opening that file and it tells me some things. It says that it's created a value x, a variable x, that contains 34 and has type int, a variable y that contains 17 and has type int, and this last line you'll always see. This is actually the result of running use and you're free to ignore it. I can now continue. I could add more things to my file, but I can also just use this prompt to see things. If I type, x;, it will say, "Oh that's a 34. It has type int." If I said, x+7;, it'll say, "Oh, that's 41 and it has type int." If I say x+7 and forget the semi-colon, it will wait for me to continue some longer command and so I can end it with semi-colon, or I could have split things onto multiple lines and maybe added y to that and then semi-colon, and that would be 58 and so on. We'll have more to say about the REPL in a bit, but for this video, what I want to do is just go back and continue writing our program and understand the exact meaning of what it means to have a sequence of bindings. The nice thing about this sequence, is that you can use earlier things in the sequence. If I have x+y+y+2, now what will happen is when I go to create the variable binding for z, it will be able to use the earlier bindings. An obvious question would be, can you use later bindings? The answer is you cannot and that might seem very strange or unusual, but it has certain advantages that we'll talk about in a couple of videos. But the rule, every programming language has different rules, is that you can only use the earlier bindings. The reason is, that we can actually keep track of exactly what our program means as we go along. I'm going to do this in comments, but this is exactly what the implementation of the language is doing when it sees all this code. Initially, we don't have anything. It turns out we have a bunch of predefined functions and variables, but we haven't defined anything yet. After we create this variable binding x, what we have is what I'll call it a dynamic environment. It's the environment you have when you're running the program and in that environment, let's say, x --> 34. Then, after the next one, we'll have a dynamic environment. Environment, where x --> 34 and y --> 17. That's why, when we get to this third one, we still have x --> 34 and y --> 17. What happens is, we get to this expression and we evaluate it in the current dynamic environment. When you have an addition expression, you go and evaluate the two sub pieces, so in this edition expression, the two sub pieces. When you get a variable, you look it up in the environment. We look up x, we get 34. We look up y, we get 17. Together, that's 51. Over here we'll end up looking up y again. That will give us 17, add two more, that's 19. If my math is correct, we'll get what? About 70 here so z will, in this environment, now map to 70. This is how we continue as we evaluate our program. If next, we had z+1, then I'm just going to paste this down. We'd have everything we did have on our environment, and now w holds 71. There's something that happens before any of this, and that is that our entire program, our file or sequence of bindings, is typed checked. ML is a language with a type system and if your program makes inconsistent assumptions about what's in int or tries to use a variable that's not defined, you get an error before you ever tried to run the program and that is taken care of by what I'll call the static environment. Even though I'm showing this to you second, this all happens before the program is ever evaluated, before it's ever run. What actually happened is the implementation first went through this whole program and said, "Oh, because 34 is an int, I know that, that's built into the language, x will have type int. It will hold something of type int.". Similarly, as I go back through this sequence I say, "Oh, x has type int and y has type int.". Here, now this is more interesting, the only reason that z gets to also have type int is because when I looked at this expression, when the type checker looked at this expression, and said, "Well, addition has type int if both the sub expressions on the two sides have type int. Similarly, this addition can have type int, if x and y have type int and when you get a variable, you type check it by looking it up in the static environment.". The static environment acts a lot like the dynamic environment except it just deals with what's an int or what's defined or what's not, and so it doesn't actually run the program. What really happens when you take this file is, first, everything type checks then, if that passes, everything runs. It may not look that way. If I flip over to my REPL here, and I'm always going to restart before I show you something after I've changed the file, it looks like it just figured out all together that x is a 34 and is type int, y is 17 and is type int. I really like to think of the type checking as coming before the evaluation. Let me show you a couple more kinds of expressions and then we'll wrap up this segment. First, let me show you a conditional. Here, let me finish writing it out and then I'll walk you through what's going on here. I'm just creating another variable. This one is called abs_of_z and it says if z < 0, then 0 - z else z. As you might imagine, the way an "if" expression is evaluated is different than addition. It doesn't go and evaluate all the sub expressions. It first looks at this first sub expression, z < 0. It looks up z in the dynamic environment, gets 70, takes 0, asks <, that's false. As a result, it ignores this expression between then and else, never evaluates it, and instead evaluates just the thing after the else, gets a result, in this case 70, and so the result of the entire thing, this if will be 70 and will end up therefore, putting the result as the value for abs_of_z, which is shorthand for the absolute value of z. In fact, in our dynamic environment here, we'll have everything we had before and then, that abs_of_z maps to 70. As for the type checking, the way we type check an if then else, is the thing between the if and the then has to be something of type bool, and indeed, less then returns a bool, short for Boolean, given two integer arguments. Then these two branches can have any type they want, but they have to have the same type. In this case, fortunately, they both have type int and so the result of the entire if expression is type int, which is why abs_of_z in our static environment indeed has type int as does everything else we've added to our static environment in this first file. By the way, this is a real programming language with lots of built in features like less than, and plus and minus. We didn't actually have to do it that way. There's a function defined for us called abs, which takes an int and returns its absolute value. This is the first time I'm showing you, calling a function. You might be used to something like this and you can write it that way, but the parentheses don't actually matter. You can leave them out and this would have done the same thing. That's our first program. Let me now get rid of this and just give you a little more sense of how the slides will work after I show you the code. Here's basically the program we just wrote. I like to include it in the slides so if you're looking through the slides, you don't have to flip back and forth, but we already saw all this. What we focused on here were variable bindings and in general, the way we have a variable bindings, we had val, the name of the variable, the equal sign, an expression which I'm representing here in the middle of the slide with an e and then a semi-colon. What I've just described is the syntax. Syntax is how you write something down. I haven't said what it means, that we talked about with the code and I have it here on the last slide of this little segment and that's the semantics. Syntax is how you write something, semantics is what that something means. We're dividing our semantics into type checking, which is what we do before the program runs to make sure there's nothing inconsistent. You don't use a variable that's not defined. You don't try to add something that's not a number, that sort of thing, and then evaluation, which is what happens when the program runs. For these variable bindings, which is all I showed you here, you type check the expression, that e after the equals, and use that to extend the static environment. When you evaluate the expression, that ends up extending the dynamic environment. That's this meaning of variable bindings, but it seems clear that the meaning is going to depend on what kind of expression we have. For each kind of expression: variables, additions, conditionals, less than, they're going to have their own syntax, type checking rules, and evaluation rules, and to go through those, you can go to the next video.