[MUSIC] There are just a couple more topics I want to cover with currying, and the first is that sometimes the function you want to call isn't organized the way you might wish it were. Maybe you want to curry function and it's a tupled function, or you want a tupled function and it's a curried function. Or maybe you want to use partial application but not with the first few arguments. Maybe with the later arguments and you can't do that. Given a curried function, you have to pass the first argument to it. But what we could do is use our idea of combining functions to, once and for all, write very generic, very reusable functions like we did with function composition, that let us change one kind of function into another. So let me motivate that with a short example. We've seen this example before where I wanted to take this function range, which takes two numbers, i and j and returns a list with all the numbers from i up to j, use that to create a helper function countup that just goes from one to the number and then use that A countup function. So this code as written, will not work. And that's because this version of range, is tupled. It takes a pair. And here I tried to use partial application. Now of course, I could work around this, or I could change range, but there's a very general thing I could do, which is to take a, write a function that takes a function expecting a pair and return the same function in curried form. So it's basically takes a function and curries it. So what if I did this, I can take this function f and then I would return a function that takes 2 arguments in curried form. And then calls f with the pair because f expects a pair but curry of f will return a two argument curried function. And now, down here, for count up, I could just, and still call, instead call, curry of range. And this, will now work. So that's pretty neat, let me clean it up a little bit more, just by using the syntactic sugar we've seen before. I could of just written it like this. That's curry and at the call site, these parenthesis, are optional. We can go the other diretion as well. If we add a curry'ed function but we wanted to pass it a tuple and that could actually be useful, if you are composing functions, or chaining them together. We could take 2. We, we we could take f, and x,y and return a function, that would look like this. So now when you call uncurry, with some functions foo you would get back a function that expected a pair and then called f with 2 arguments in curried form, so that's pretty neat. let me quickly show you the types of curry and uncurry. They're very generic and I will leave you to puzzle over them, but I want to point out one very neat thing. There is a very deep connection to logic here, you're not responsible for this, but if you have studied logic Read these as logical formulas where the star is and, and the arrow is implies. And you'll see that these are actually true logical formulas and that hints that there's actually a very deep connection, a very mathematical connection between tuppling and currying. And I'm going to leave that as a mysterious statement for you. one other thing I wanted to show you that also has these logical formulas. Once you look at their type, is switching the arguments of curried functions. So if you had a 2 argument curried function and you wanted to partially apply it to the first argument, or to the first argument instead of the first, you couldn't do that unless you took that function and passed it to this function first instead. So, f takes two curried arguments, but other curried of f will just take the arguments in the opposite order. It takes an x and a y and then it calls f with y and x and we've seen before there's syntactic sugar for this. We could just write it, that way. Okay, so just more fun playing around with combining functions. Hopefully I've shown you that this thing is at least a little bit useful. And functional programmers do often program with these things, in order to get things elegant, and pretty, and arranged just how they want. So, that was one topic I wanted to discuss. The other, is people often want to know, isn't currying really slow? If I want to create all these closures to call a function. And it turns out, that it depends, and that's up to the language implementation. And language implementations can actually make curried functions very efficient. So in general, both calling a function with a tupple, and calling a function via currying with multiple arguments. These are plenty fast. These are constant time operations. You should program in a way, that, makes your code elegant, short, concise, and correct. Alright. Well then maybe you might want to know which is, is faster. This is not part of the language definition. It will depend on the language implementation. And it turns out that the implementation of SML that we are using, the SML New Jersey compiler, does faster with tupling than with currying. So kind were in fact were be a bit slower for the function calling times and times and times of time for performance critical application where it actually matters, I should point out this is actually not necessarily the case, in fact most of their functional programming language implementations out there today OCaml Fsharp Haskell to better with currying, than with. Coupling. Now, the optimizer might do very well with both of them. But in those other languages, we tell performance conscious programmers, use currying. It'll work just fine. If you use partial application, which is something up to callers. That might be a little bit slower. But in languages where currying is always the norm, we tell programmers even when they're learning to program, oh it's just the 3-argument function. And the same way I lied to you at first and told you that tuple's version was a 3-argument function and then went back and told you the truth. That's what these other languages do with currying. Currying is the default. Almost everything is curried and you only tuple things in those situations where