It in this segment I want to introduce the last major language construct will use just a little bit on homework one and that's options and to motivate this I'm going to go back to this function we've seen before for computing the maximum of a list. So this old_max function, old because we've seen it before takes in an int list and returns an int. And we like it in many ways it's efficient and how it does it's recursion and everything. But I never liked how it treated the empty list. There's no such thing as the maximum integer in an empty list and returning zero was always an awkward workaround. Now you could try to return a really negative number or something but I'd prefer to say that you should not try to compute the max of an empty list. So what should we do? Well there's a few things we could try to do. We could say that's a runtime exception. And and we should raise an exception just like if you try to divide by zero or take the head of an empty list and we'll see exceptions at some point. But in this segment I want to actually try to return something useful. So another thing we could do given the constructs we already have is to change Max so it doesn't return an int it returns an int list and what we do is if you pass it the empty list will give back the empty list in the past that the non-empty list would return a one element list holding the maximum of all the numbers that were in the argument. And that would work but it's poor style. And the reason why it's poor style is this returning zero or one thing is common enough in programming that ML has a different type and a different set of language constructs that's designed for this and it's better style to use it so that users of your function understand that's how it works. Whereas a list can hold any number of elements when you have the zero or one situation you want to use an option instead. So it's pretty easy to understand options and the way I like to explain them is by analogy with lists. So we're going to have a new kind of way to build a type, the same way we could write t list for any type t we can now write t option for any type t. And these are different types. Options are not lists. Lists are not options. It's just an analogy to make it easy to teach. All right. So just like with lists we had a way to build lists and ways to access the pieces we have the same thing with options. There's two ways to build an option. You can write NONE in all capital letters and that builds an option that holds zero items the same way bracket bracket builds an empty list. Or you can write SOME in all capital letters and then an expression. And the way that will evaluate is you evaluate the expression e to some value and if that value has type t you end up with a t option much like creating a one element list. So that's how you build it when you have some of something like some of three. That's an int option and you can't use it like an int because it's not an int, it's something holding an int. So when you have an option you have to access it using these last two built in functions. They're really just library functions. The first one is called is some and it takes in an option and returns true, if it's a sum and false if it's a none. So it's a lot like null for lists except it's actually inverted. We returned true for the non-empty case, for the one element case. Then we have one more construct and that's valOf. And that's the thing that takes an option and gets the thing out from underneath the sum. All right? So that will raise an exception if the argument to valOf is none. If the argument is some, you'll get the piece back. That's all there is to options. So now let's use this to implement a better version of max. And I've actually already written it out this time. So this is, I'm going to show you two ways so this is the first way so I've called it max1 and this is now a function that's going to take in an int list and return an int option. All right? So if the argument xs is null then what I want this function to do is evaluate to none. That's exactly what I have here. So I'm always returning an option, in this case it's none. How about I recursively figure out the max of the tl and I'll store that in tl_ans because we've learned our lesson there. All right? Now I need to remember that the value and tl_ans is an int option. So the only way I can access it is with isSome and valOf. So what I could do is say if it's a sum and it's value is greater than the head of the list then that's the maximum return tl_ans. Otherwise either tl_ans is none because a tl of xs was the empty list or the head of the list is bigger than the rest of the list. And in either case what I want to do is return this option. I want to build an option out of hd xs and construct the option itself with sum. By the way this is the first time I've ever shown you end also. This is really just something it takes two booleans and computes their conjunction and I'll explain that in more detail in the next segment. Can't always get everything in exactly the right order. All right. So this max will work. It works great. How about we try to run it? You'll see that I've already got the second version implemented here as well. So what you see in this file are three functions old_max which takes an int list and returns an int, max1 and max2 which both take an int list and return an int option. So if I call max1 with say the list three, seven, five, I get back some of seven. What I cannot do is say take that and try to add 1 to it. That doesn't type check because what I got back was not an int I got an int option. What I have to do instead is valOf max1 of three, seven, five. And then I could add one to that and that would work fine. If I say max1 of empty list I get back none and if I try to say valOf that I get not a type error but actually a runtime exception just saying that uncaught exception option just like if you tried to take hd of the empty list you get uncaught exception empty. All right. So that was a good solution of max1. It works in a way that clients can understand. Let me show you a second version that's a little bit better in terms of implementation but works exactly the same way for clients. What I don't love about Max1 although it's okay there's nothing wrong with doing it this way is every time I come back from the recursion I'm checking whether it's a some or none. And that none case was only for the empty list. So at the very last recursive call I'm returning none, for the one on one list I return a some and then another some and then another some and I'm checking for none every time. All right. So you can avoid that. So here's a second version of max2 that is arguably a little cleaner. And what it does is of course if you pass it the empty list it would return none because that's the right thing to do. Otherwise let's create a recursive helper function that will take care of computing the max of what we now know is a non-empty list. Right. So what this function does is take in a list that it assumes is not empty. And this function has type int list arrow int. And since xs is never empty it can just do the natural thing and that natural thing is to just test 0. If it's the one element list then return that one element. Otherwise recursively figure out the max of the tl and then compare it with the hd and return the right thing. And since I only ever call max non-empty with a non-empty list either right here to start the recursion or recursively here because in the case that I am almost empty I do not recursively call it on the empty list I just immediately return, this will never raise an exception. So when down here I called max non empty on xs I will get back an int which is the maximum element of the list but then max2 can't just return that int, it has to return an int option so it uses some to return the result. All right? And we can check that that works as well. So let's just try Max2 of three, seven, five in which it gets seven. You see that there at the bottom, some of 7 excuse me, whereas max2 of empty list still returns none. All right? So either max1 or max2 work. I prefer max2 just a little bit but they're both fine style. And now we've seen how to use options and how they're a lot like lists except instead of having any number of elements they just always have zero elements or one element and that's options.