[MUSIC] In this segment we're going to start our study of currying, our next closure idiom. It's one of my favorite things to do in functional programming. and this is a new way to deal with conceptually multi-argument function. So you might remember that in ML, every function takes exactly one argument. We worked around this previously by passing n arguments as n different pieces of a single tuple. So another way we could do it which is called currying, is to take one argument and return a function that takes the next argument and it we'll still be able to use the first argument, because it will be in its environment. This is called Currying after the name of the person just as a funniest side, I actually spent years of my life before I knew that, trying to figure out why it was called currying, and of course, I was never successful. So, let me show you an example in the code of how this is going to work. So, we are going to stick with a very simple example in this section of just a function that takes three arguments conceptually, x, y and z and sees that they're sorted. So in terms of tupling, just take a triple, pattern match against it like this, and return true or false based on is z >= y and is y >= equal to x. And we would call that tupled function with a triple like 7, 9, 11. So here is a new way to do it that at first will seem very ugly, but then I will show you some syntactic sugar that will perhaps make it even cleaner, even more pleasant than the tupled version. So let's just make a sorted3 function that takes in an x and returns, these parentheses are not optional or are optional, so I'm going to take them out, a function y that when you call it, returns a function z, a function that takes a z, and when you call it says z >= y and also y >= x. Now that looks a little funny too, we could have instead said it fun sorted3 taking an x and then return a function y that when you call it, takes a function z and so on. That's exactly the same thing so maybe the val version will be a little easier here. And now, what we can do is we could call sorted3 with a number, like 7 and that would give us back a function, right? If we call this with x, we're going to get back this. So what we could then do is call that function with 9 and that would give us back this function, and then we could call that with 11. And this will absolutely work and should even give us the right answer, so let's see. sure enough I have some lower stuff in the file, ignore that. sorted3_tupled takes a tuple of ints and returns a bool. t1 was true. Sorted3 takes an int, returns a function that takes an int, and returns a function that takes an int, and that all returns a bool, and then we did use it correctly, and so t2 is true. So let's take a closer look at what's going on, because that looks awfully complicated. It's all the same semantics, we already know about closures. So when we called (sorted3 7), we got back a closure. Remember, a closure has two parts, a code and an environment. The code is just the body of the function we called fn y, fn z, z >= y, and also, that's the function we got back, we called with (sorted3 7). It returned this function that takes y and the environment for that closure is that x maps to 7. So when we call that closure with 9, we get back a closure whose code is now fn z, z >= y and also y >= x, because that's what the result is of calling the function with y to 9 and in the environment, x maps to 7 and y maps to 9. So when we call that closure with 11, we evaluate the and expression, and we get back true, that's all there is to it. And, while the semantics may seem complicated, it's just closures which we get used to. And since currying is such a common pattern, such a common idiom, we don't think through it on this level every time. We just say oh, I'm using currying, so it's like a multi-argument function. And, so now, let's make it even more pleasant to use by pointing out some syntactic sugar that we happen to have in ML. So, it turns out, the first thing we can clean up is this call. Okay? So we don't need all these parentheses. In general, if you just leave the parentheses out with spaces between arguments, the parentheses go in to organize things to the left. So if you just write sorted3 7 9 11, it's calling sorted3 with 7, getting back a function and calling it with 9, and getting back a function and calling it with 11. So we don't need those parentheses. We can go back to our code here and instead, just say val t3 = sorted3 7 9 11. And now if you compare this to calling a tupled function, it's actually fewer characters, more space characters, but less clutter on the screen, so that's actually kind of nice. And this is a good time to point out that you have a curried function, like sorted3, you can call it either of these two ways. If you have a tupled function, you can only call it this way, you can't mix and match, right? If you want to call a function that takes a tuple, you have to pass a tuple. And if you want to call a function that takes, that's curried, you have do via via a sequence of calls. So you can't, for example, write sorted3_tupled 7 9 11. That's going to try to call sorted3_tupled with 7, you'll get a type error immediately, because you're not passing a tuple where you need it. And similarly, you cannot call sorted3 with a tuple, you will also get a type error. It doesn't expect a tuple, we can see here in the greater than, y >= x, that x needs to be an int and not a triple int, so we better comment all that out. Okay? So, so far, so good. That's the first step of syntactic sugar, is that callers can just think oh, it's curried and takes three arguments. I'll just separate them by spaces. It's also easier to define curried functions than I've suggested, that you don't have to write all these anonymous functions that return other anonymous functions. That you can, or syntax for function binding has built in support for currying. So, I have the definitions here written on the slide, but it is sometimes easier just to show an example. Here is another definition of sorted3, which I'll call sorted3_nicer. If you just separate multiple patterns in general, here just variables, before the equals, this means curried Alright? So y >= x, and so, compared to our previous version here, these are exactly the same, this is syntactic sugar for this, although, because we used fn, we could also use recursion, we don't need recursion here. So given this that's a much nicer way to write the function, and we can continue to use it using our syntactic sugar, and that is a really nice way to think of multi-argument functions. Just the caller, separated them by spaces, the callee and the caller, separated them by spaces, but what is going on semantically is closures, functions returning other functions, the rest is just syntactic sugar. I would point out that because this is just syntax, you could call sorted3_nicer with all these parentheses, because this means exactly the same thing as the line and a buff, 'kay? So that is what most of what I wanted to show you. Remember here, over in the over in SML, in ripple, that these tupled functions will print their arguments looking like this, sorted3_nicer, we'd have exactly the same type. Remember, the parentheses go to the right here, so this says, I'm a function that takes an int and returns an int -> int -> bool. meaning that you passed that function in int and you get back a function, you pass that function in int and you'll get back a bool. So as you can, here in the alpha to the ripple, I had one more thing I wanted to show you, which was a fold in a curried form. So we've seen fold before, it was a couple of segments ago. Here is a version that takes three curried arguments using our syntactic sugar. So this first line right here that I'm highlighting, means exactly the same thing as on a function fold that takes f and returns a function that takes the accumulator. If you call that, it returns a functions that takes x's and this is its body. And you'll notice that here in the recursive call, since I have a curried function, I need to pass those arguments separated by spaces and I've done that. Here is the first argument, here is the second argument, and you need these parentheses so that you know where the second argument ends and this third argument begins. So that's a perfectly fine curried function. Here is a use of it. Here is a function that sums all the elements in a list by just calling fold, which here is curried. Here's the first argument, space, second argument, space, third argument, exact same semantics as sorted3, just more useful. So, coming back here, in terms of sorted3, our final version here is really very elegant. It's actually fewer non-space characters than the tupled approach, the approach that used tuples, and we just know that it's syntactic sugar for this bottom version, which is easier to understand what's going on. But once you get it, once you go oh, that's what curring is doing, then you just think of it as a three argument function, like we've thought of tuples as multi-argument functions. And then for fold, we just write it this way to begin with. It's just as elegant. We think of fold as a three argument function and we call it with three arguments.