[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 the 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 in Dr. Racket and 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 RPL here. And now, let's do a couple of variable

definitions. So, (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, a 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 plus is really just a function

so plus is a function and we call it here.

So, this variable y is being bound to the result of this function call and in

general, function calls are written with a perenthesis before the function your

calling, then the argument, then a parenthesis after the arguments.

It's a different syntax than in languages you may be familiar with but that is a

function call calling the plus function with x and 2.

So now, let's define our own function. Let's 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

key word lambda, it's spelled like the Greek letter.

Racket, in 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 wanted to find a function, put the

arguments in parenthesis, and then you have the body.

And the body I want is to call the multiply function with two arguments.

With x and with the result of this other call x and x.

And then, and that call, this call the lambda form and the defined form.

So, this body, the, 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 parenthesis. I'll talk more about parenthesis 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? It takes in, this an anonymous

function that takes in one argument, x, and has this body that ends up cubing x,

alright? 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 kind of 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 it 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 this really is just a function call and so it makes 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 Racket, our a functions really do take

0, 1, 2, 3, 4 or any number of arguments. It's not syntactic sugar for coupling 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 the variable cube3 to be bound to a function

that takes one argument x, and returns, has this as its body, x times x times x.

If you had multiple arguments here, you could just do like that before that first

right parenthesis. So, there are three versions of cubing

functions. Now, let's write some recursive

functions. It turns out that unlike in ML, we don't

need anything new to do recursive functions, but you can just use the

lambdas like we have been doing or the syntactic sugar I just showed you.

So, if I wanted to find 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 y only works if y

is non-negative, alright? 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.

You want e2, e3, and that is the thing to test for.

The true branch and the true, false branch, so we don't use keys then and

else, so 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, I want to

say if y=0, equals is 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 * x.

and then recursively call pow1 with x and y-1.

Notice that like 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, this, sorry, if

expression. The if expression has equal y0, 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 we, every time we have a function call, its parenthesis function

you want to call, arguments, okay? 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 can say pow1, how about 3^2,

right? So, it's a function call.

I pass in the two arguments. I get nine.

And if I ask pow1 3^0, I would get one,

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.

and so we can, we can do that in Racket. it's not as common in Racket because

Racket has built-in support for multi-argument functions but there's no

reason why we can't use curreying so let's see.

Well, here's a simple version. I could just call pow1 with the two

argument, right? So, this pow2 is a function that

takes in one argument, x. Its body is this lambda, which returns a

function that takes 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 this pow2, I could partially apply it and I could

say something like pow2 3, okay? And if I save all that and run it

I could say, three-to-the with 2, and I would get 9,

right? Because I end up, taking this function that pow2 return, calling it

with 2. That ends up calling pow1 with 3 and 2,

and I get 9. So, it's currying exactly like an ML.

because it's less common, if you're not partially applying things you know, 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. This parenthesis matter.

Parenthesis 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

the function, and if I want to call that function with 2, 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. 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 parenthesis e0, for the expression that evaluates to the function 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.