[SOUND] Alright in this segment I want to take a brief break from building up our conceptual framework for understanding ML to go through a couple more pragmatic topics namely how to use the REPL, that Read Eval Print Loop effectively as well as how to deal with error messages and show you a bunch of examples of errors that are fairly common when starting to learn ml. Okay. So we want to ask a couple questions. First of all is how do we run programs using the RPL and what does it mean to have a REPL? And then what happens when we make mistakes and how can we go about debugging those mistakes? And fundamentally, debugging is, is a skill you develop over time, and I just want to give you some practice with it by watching me do some. So, the way we've been using our repple, was primarily with this use expression, and really the way that I want you to think about it, is that it takes the contents of the file, and it's like you typed in those bindings, those variable bindings, one at a time into the REPL. And that really is what happens. So if I take this file which we've seen before, it has a bunch of bindings. When I come over here with Control C, Control S, Return to bring this up. I could manually type these in one at a time, val x equals 34, val y equals 17 and so on. But instead, when I say use first dot sml, it does that but all at once in a batch showing me the result of doing all of those bindings. What were their types and what's the result of evaluating them. And that's all that it's doing, and it's convenient that way. And so when you look at it this way, what is actually going on is the meaning of our programs is that all we have is a REPL. And use is just a convenient way to use that REPL. So, REPL stands for Read Eval Print Loop and it actually pretty well named. But what happens at that prompt, when you type in a binding, is that it reads it. It evaluates it, although if it doesn't type check, it just gives you an error message to that extent. It prints the result, and then the loop part is about how it gives you another prompt back so that you can continue. So we can just think of this as a strange way to run programs. Where we open up the repple and then we type use. But it's also quite convenient for after you type use, to then go ahead and try a few things out. Now after you types Us you find yourself typing the same thing over and over again. Like you're building up a collection of test cases for say your homework problems. You're probably not making an efficient use of your time. And it's better to go ahead and move those tests into a second file, and then go ahead and use one file, then use a second file that's going to include all your tests. And then maybe do a little extra playing around. But what I don't ever recommend, for reasons we'll discuss in the next segment, is typing use, playing around and then using the same file again, instead, what you always see me do is come over here to the repple, type control D to end my session, control C, control S return to restart it and then it's okay to type use again with the file. The reppa wont stop you from doing it another way, but I don't recommend it because it's often very confsing what's going on. Okay. So now let's turn to errors. usually when I show you programs here in the video, they just work in trying to demonstrate something. But we all make mistake. You can make a syntatic mistake, you don't write something down the way you expected. You can make a type checking mistake, what you wrote down is the correct syntax, but it doesn't follow the type checking rules for the language console you're using. Or, it might type check and then run. And either, it it produces an exception, or goes into an infinite loop, or it produces an answer, a value, but not the value you wanted. So debugging has to attack all of these problems, and one of the hard things is you often don't know which mistake you made, and the error message you get from ML may not help either. And there's a few reasons for that. Well the, the good reason is, well you wrote something that isn't what you intended. So whatever error message you get is just ML's best guess as to what might be the problem. But it's up to you to figure out what actually the problem is. And the other thing is, is that as much as I love ML as a language, and love having a read of val print loop, the error messages you get particularly when you have a type checking error, are usually actually quite bad. And, it's really a bit of an aquired skill to look behind them and figure out what you did wrong. So the best way to learn something is by trying it and I want you to just try writing in all programs. Don't be afraid of errors, slow down, find what line number the error's coming from and so forth. And I thought I would help point you in the right direction by just doing a little bit of that myself. So I have a second file here that is called errors.sml and it looks like a pretty good program here. It turns out it has a bunch of errors and this is the entire thing but suppose I wrote all this down. And now I go over here and I say, use errors dot sml, 'kay? So it turns out, it gives me a couple errors here. The first one you can see is at line fourteen and it says, syntax error inserting else ID. Okay? So if I go over to line fourteen. Which you can see here in emacs down at the bottom. It prints out the line number. That line is just val a = -five. So it's not, you can't look at that line, and figure out why it's inserting an else. It turns out, is often ca-, the case. Well, the error is actually a little bit before the line number that's being reported as the problem. And indeed if you look up here I have this if then expression. Well, in ML, there's no such thing as an if/then expression. You need an else afterwards, which it thought you might want to put on line fourteen. I actually want to put it up here. And I have to have else something. How bout else 42? And that's because, as we know, when you have a conditional expression, either branch, the then or the else might need to be evaluated. So you can't leave the else off like you can in some programming languages. So, okay. We fixed that error. Let's go back here. Come down to the end. Restart things. Try again. And by the way, if you don't want to keep typing this, you can type meta p to get your previous commands back. And now we see an error on line eighteen. It says replacing fun, with wild. Now if you look at line eighteen here, it might look just fine to you. Why can't I have a variable called fun? Well, as often happens when you're learning a programming language, we stumbled across a keyword. It turns out fun means something else in the language and we're not allowed to use it for a variable. so we're going to have to change this and how about funny. That should do the trick. Quit. Restart. type that back in. And now, we get a whole bunch of error messages. They don't even fit on the screen. Because we're now, don't have any syntax errors that ML found. So it's giving a bunch of different type errors. And I like to fix the first one and then come back. So, up here at line 8, it says, unbound variable or constructor x. So if I look at line 8. Sure enough, I am using x right here. yx+1. equals x + 1. But it sure looks like it should be bound. It should be in my dynamic environment from the previous line. But it turns out that the error here actually is syntax, even though it looks like type checking because I'm not actually finished with the previous expression. If you want to start another expression, you have to type val again. Since I left that off the type checker thought this entire thing was one expression and for this expression, there is no x in the dynamic environment yet because I haven't finished defining it. so I have to put val here. By the way, I used to put semicolons at the end here. And you still can. You have to in the REPL. But in a file, it's not actually necessary. So it turns out that was not the error. But leaving off the val was. So, alright? So we'll try this again. And we still have a bunch more errors. But at least now, we're up to line 10. Where it says, test expression in if is not of type bool. If we go over here to line ten, a ha, it actually got one right. This is actually very accurate error message. Right here, this expression Y, has type ent, because that's the type of the variable Y, and you're not allowed to have something of type int there. You have to have something of type bool. So, this is just a nonsense code, but maybe the programmer meant to write, if Y is greater is zero. Okay, so we fixed that one. Come back here, restart. Try it again. Still a bunch of errors. Still on line 10. Types of if branches do not agree. we remember that the then branch and the else branch both have to have the same type. So that, that can be the type of the entire if/then/else expression. And, indeed, 34 is type int. And x less than four has type bool. So I don't know which of these is wrong, but I have to fix one of them. How about fixing that one? Alright, back we go. I hope we don't usually make this many errors in this few lines of code but we're up to line 14. Expression or pattern begins with in fix identifier minus. This one might not make you very happy at all. It's actually complaining about that minus five and maybe that seems crazy to you but in ML the only thing you can use minus for is as a binary operation like X-5 or 0-5 or 13-5 or so on. If you want to write a negative number you might well say 0-5 will work. you don't have to do it that way. there's just different syntax in ML. When you learn a programming language, you have to learn that language's syntax rules and it turns out that negation of one argument is the tilde character, with or without a space here not the minus character. You can't use minus. You have to use tilde. And that will fix this problem. and, we're up to line twenty. Operator and operand don't agree, real star real, int star int. The expression it's complaining about is this X slash W, where presumably I was trying to do an add division. Well, that is how you do division on floating point numbers in ML which it calls reals, but it doesn't apply to integers. You're not allowed to use slash on integers in ML. That's just the type checking rule, but there is a different operator for division and it's spelled D, I, V, for div. Alright, so we maybe look that up somewhere. and we got that fixed and now we can run this and. Ha, that looks like a very different kind of message. So it turns out we're not getting a type checking error here at all. We're now actually, everything type checked and we're running the program. But when we ran it we got an uncaught exception for divide by zero. Like in many languages you get an error if you divide by zero when you run the program. It's not a typing error and sure enough if you look at this X div W, you go to evaluate W, we look it up in the dynamic environment and we get zero. So if we don't want that error we're going to have to use some different addition division. How about dividing by W+1? So let's go back here one more time. And look at that. We actually ran. We have a bunch of types now, we have a bunch of values. But if you look at the N, not this val it. That's the result of the use itself. But the last variable by name we did. I created a variable fourteen, and it is bound to the value zero. Of type int. Now that's not necessarily a problem, but maybe it's not what I meant. And I brought this up, I included this just to remind you that sometimes you get this, great sense of satisfaction when it all type checks. It all runs, but you still have to make sure you have the right answer, and if I wanted this to be fourteen, I probably didn't want seven minus seven. I wanted seven plus seven. Of course, there's no way a type checker or an automatic tool can know what I meant. Fourteen is just an English word, but you still have to test your program, and, and look at the answers and make sure it all works. And in this case, after fixing that. Finally happy with what I've got and so let's stop there.