[MUSIC] So let's now jump in and get the Racket basics out of the way. Let's learn how to define functions, variables, conditionals, and so forth covering a lot of ground we already did in ML. I have a few slides posted with this lecture, but I think I'll primarily just stay over here and DrRacket will write a bunch of code with you. So I already have #lang racket and this thing so that I could test in a second file if I wanted to. Although we'll just use the REPL here. And now let's do a couple of variable definitions. So parenthesis define, the name of the variable you want to define, and then an expression that you evaluate to the variable. So this is really like val x = 3 in ML, okay? And now we can do another one. So definition can use x. So suppose I want y to be x + 2. So what I do is I call the plus function with x and 2. The way you call a function in Racket is you write parenthesis, the function you want to call and then the arguments. So plus really is just a function, so + is a function, and we call it here. So this variable y is being bound to the result of these function call. And in general the function calls are written with the parenthesis before the function you're calling, then the arguments, then a parenthesis after the arguments. It's a different syntax then in languages you may be more familiar with, but that is a function call. Calling the plus function with x and 2. So now, let's define our own function. I'm going to write a few versions of the cubing function. So I'll call this one cube1. And now I'm defining a function. So, what I'm going to do is I use this keyword lambda, it's spelled like the Greek letter. Racket and earlier dialects of this language like scheme have been using that Greek letter for decades. It's a bit of a strange choice. Then the arguments in parenthesis. So this will take one argument, so lambda is a keyword that says I want to find a function, out the arguments in parentheses, and then you have the body. And the body I want is to call the multiplied function with two arguments, with x and with the result of this other call, x and x. And then end that call, this call, the lambda form and the define form. So this body, just the body here, this part here, would be like in other languages writing x times x times x. But in Racket, everything always has the function first, and all these operators are just functions, and so it looks like this. We get very used to, in Racket, ending things with lots of parentheses. I'll talk more about parentheses in a future segment. But for now, notice all I did was introduce a val binding, right, for cube1 and bind it to this anonymous function. So, lambda is like ml's fn, right? This is an anonymous function that takes in one argument x and has this body that ends up cubing x, all right? Let me write a nicer version. It turns out that you don't have to write it that way because the multiplication function which is provided to us already by Racket, can take any number of arguments and it returns their product. So we really can just write it like that. So multiply in this language is a function that can take any number of arguments. There is a way in Racket to define your own functions that take any number of arguments, but I'm not planning to show that to you. You can consult the guide if you need it. You won't need it for any of our homeworks. The other thing I wanted to point out here is that is really is just a function call. And so it make sense that we're calling it that way. Our function cube2 takes one argument. Multiply takes any number of arguments. Unlike in ML, I'm not lying to you, this is not syntactic sugar. In the Racket, functions really do take zero, one, two, three, four or any number of arguments. It's not syntactic sugar for tuppling or for currying, okay? Let me show you something that we do have syntactic sugar for, though. You do not have to write lambda every time. If you want to do this, this is exactly like the previous version. So what you can do is instead of essentially defining a variable and binding it to this anonymous function, you can use this syntax instead but it is exactly the same thing. This is syntactic sugar for define variable cube3 to be bound to a function that takes one argument x and has this as it's body. x times x times x. If you had multiple arguments here, you could just do like that before that first right parentheses. So there are three versions of cubing functions. Now let's write some recursive functions. It turns out that, unlike in NML, we don't need anything new to do recursive functions, that you can just use the lambdas like we have been doing, or the syntactic sugar I just showed you. So if I want to define the exponentiation function, I'm going to do this two different ways. So I'll call this pow1. The purpose here is x to the yth power. And I think my solution only works if y is non-negative, all right? I just need a body here. And now I need an if. The way you write an if in Racket is you write left parenthesis, if, and then three expressions, e1, e2, e3. And that is the thing to test for, the true branch and the false branch. So we don't use keywords then and else, they don't exist in Racket. We just write the three expressions in a row and then end with a right parenthesis. So the way I want to do this, is I want to say if y = 0, equals is a function that takes two numbers, returns true if they're equal. Then 1, so I've written two of my three expressions for if. And now my third one can be times x. And then recursively call pow1 with x, and y- 1. Notice that every operator in Racket minus goes first and there it is. So pow1 is a function that takes two arguments, x and y. And its body is this if expression. If expression has equal y 0 for its first sub expression, 1 for the second. And multiplying x by the result of this call, this call, pow1 with x and y- 1. So this is the exponentiation function. You'll notice that every time we have a function call, its parenthesis function you want to call arguments. So this will work fine. Why don't we go ahead and run this? I haven't been running much for you. So I just clicked run. Now, I could say pow1. How about 3 to the second power, right? So it's a function call. I pass in the two arguments. I get 9. And if I ask pow1, 3 to the zeroth power, I would get 1. Great, okay? So let's define just a couple more functions. Let's do another version of pow that's curried. So currying has nothing to do with anything other than an idiom with closures. So we can do that in Racket. It's not as common as Racket, because Racket has built in support for multi r unit functions. But there's no reason why we can't use currying. So let's see, well, here's a simple version. I could just call pow1 with the two arguments, right? So this pow2 is a function that takes in one argument x. Its body is this lambda, which returns a function that takes in an argument y, and then I just call pow1 with x and y. Of course I could have my own conditional down here if I preferred, okay? And now that I have this pow2, I could partially apply and I could say something like pow2 3, okay? And if I save all that and run it, I could say three-to-the 2 and I would get 9, right? Because I end up taking this function the pow2 returned, calling it with two. That ends up calling up pow1 with three and two and I get nine. So it's currying exactly like in ML. Because it's less common if you're not partially applying things, so if I wanted 16, it's quite convenient to call pow1 with 4 and 2. But if I want to do it with pow2, well, what do I need to do? I need to call pow2 with 4. That gives back a function, and now I need to call that function with 2. These parentheses matter. Parentheses always matter in Racket. If I want to call pow2 with 4, I have to write it like this. Then that gives me back something that is a function and if I want to call that function with two, I need this parenthesis to its left and then here. So it turns out that in Racket there's a little bit of syntactic sugar for defining curried functions. The code posted with this segment will have that. You don't need to use it. We're actually not going to use currying so much in Racket. There is no syntactic sugar for calling a curried function. And this line that I have here really is the best that you can do. I bring up currying here both because it's something familiar and I wanted you to see it in multiple languages. And also because it emphasizes that we have anonymous functions, first class functions, and whenever you want to call a function, it's always e0. So parentheses, e0 for the expression that evaluates to the function that you want to call. Then e1 up to en for the arguments, then the other parenthesis. This is what function calls look like in Racket. Now if e0 is not an expression, if it's something like if or define or lambda, then those are not function calls. Those are other constructs in Racket. We'll continue to see those and understand those in the segments ahead.