[MUSIC] Let's talk some more about parentheses, and let's particularly understand that parentheses are not optional in Racket. They are common, but every time we use them, they have a meaning. So this is a habit you have to break yourself of. In languages that don't have a syntax like Racket, you're used to just putting in extra parentheses to help you understand something. And if something isn't working, maybe you'll just put in more parentheses, and then it will start working. That doesn't work in Racket, the parentheses always have a meaning. In particular, in most places, if you're writing something in parentheses, that means evaluate e to a result, and then call it as a function with zero arguments. Because the way we do a function call is parenthesis, thing you want to call, and then argument. So if there are no arguments, this is, call it with zero arguments. So look at this one with two parentheses. This says, evaluate e, call the result as a function with zero arguments, get back a result, and call that as a function with zero arguments. This makes perfect sense. We mightn't even do things like this, but if it's not what you mean, you're going to get an error message. You're going to try to treat something as a function, that is not a function. Now, without static typing, this sort of thing will work just fine when you save your file, when you click Run. But once you actually execute the code, maybe it's inside a function body somewhere, then you can get an error message. It can be hard to diagnose, and your first reaction is to just start playing with the parentheses, and that's only going to get you into more trouble. So let's work through some examples to give you some practice with this. And the moral of the story is always, slow down, think about your parentheses. If you're confused why they're there, delete them and start over, indent your code well, it'll all work fine. So what I'm going to do is just show you a bunch of versions of a factorial function, one of my favorite little functions for examples. And I'm going to start by getting it correct, okay? So so far, what I've written while I was talking to you is that fact is a one-argument function, so these parentheses have to be here. Then I have an if, and I need three arguments. This is the first one, it's a kind of call to the equals function. This is the second one, which is 1. And then this is the third one, which is multiplication of n. And then another call, always put a parenthesis before the call, of fact. To get the argument to that, I need to call minus with n and 1. Close, close, close, close, close, and let's run this. And if I do fact of 5, I get 120. And if I do fact of 10, I think I get about 300,000. 3.6 million, excuse me. Okay, so that version was right. Now let's do a bunch of version that are wrong and try to figure out why. So let me do, I'll call it fact1, n, if (=n 0), then 1, else n fact1 of- n 1. Close everything and run it, it all seems to be fine. I call fact1 with 5 [COUGH], and I get procedure application: expected procedure, given: 1 (no arguments). And that's exactly right. If you look up here, what I did while I was talking to you and typing, is I put this 1 in parentheses. And as a expression, that means call 1 as a function with no arguments. There's no type checker to separate our functions from our integers. But when we went to execute this, in the base case, when n was 0, that's when we got the error. So we had already made about five recursive calls, and then we got the error. And we would fix this up by deleting these parentheses. We can just leave this in here, because as long as we don't call that function, it won't be a problem. Let me show you a small variant, this is fact1b. Suppose I made the same mistake, all right? Just like this, all right? So you might think, if you're not paying very careful attention, that this fact1b is exactly like the first one. And yet, it totally seems to work. In fact, this will work for almost every argument. The only argument it won't work for is 0. So what's going on here? Well, here I actually made a totally different mistake. This is wrong, if you call fact1b with 0, you will try to apply 1 with 0 arguments. But I'm not actually using fact1b recursively here. I wrote fact here, right? I didn't write fact1b, I wrote fact. And so in fact, pardon the pun, when I call fact1b with 5, I end up not calling fact1b again, but going up to this first correct version. And so that's we didn't get the error, unless we called fact1b originally with 0, okay? Good, let's try another one. How about fact2, excuse me, I need this parenthesis here. How about if = n 0 1, otherwise n of fact2. I'll remember now to call the correct thing recursively. And like that, and click Run. And this is actually a syntax error. So this, it will not allow to start, I don't have to test it out to get in there. DrRacket will detect that, we have a good error message here, if has 5 parts after the keyword. If is always supposed to have 3 parts, and yet, clearly, syntactically it has 5, = n, 0, 1, and this multiplication. And that makes no sense, if has that 3, and what happened is I forgot the parentheses around the function call to equals. Okay, how about if I do it this way? If, so I'm going to get almost all this right. Three terms, multiply by n, fact of- n 1, just like this. Click Run, and I get, bad syntax (multiple expressions after identifier), indeed I do. So if I say define, and a variable, notice I forgot this parenthesis after the fact3. Then it's expecting like a val binding in ML, right? That I evaluate something here, but I have two things after the variable. This is the first one, this is the second one, right? I messed up one parenthesis. This left parenthesis is supposed to be over here, before the name of the function, not before the argument list. Okay, parentheses matter, I know I'm typing fast in order to keep the video short, but you should think, which concepts am I using? And in this case, if you're defining a function, you put a parenthesis before the function name. You do not put a parenthesis before the argument list. Look up here in the collect version, I have this, and then I have my function body, okay? All right, let's do another one. So I need to comment these out, these ones, so that I can get the other ones to go ahead and click Run, so that I can test them out. Here's my fourth version of fact. How about if (= n 0) 1, otherwise multiply n by my recursive call to fact4, with (- n 1 ). Click Run. This compiles just fine. Call fact4 with 0, I get the right thing, 1. What if I called fact4 with 5? I get an error message. And it says that star expects type number as 2nd argument, given: procedure: fact4. That's exactly right. So it turns out that multiplication, we saw back in our first or second segment on Racket, can take any number of arguments. And here I'm passing it three arguments, n, the function fact4, and n-1. Functions are first class, so you can pass them to other functions. But then the body of multiply says, wait a minute, I don't have a number, I'm going to raise an error. A type checker in a language like MO would catch this. In Racket, we have to test our functions to test this sort of error, then we need to fix up our parentheses. We need an extra parenthesis before fact4, and then after it, in order to call multiply with two arguments, not three. Okay, let's do a couple more, here's fact5, Of n, if (=n 0) 1, otherwise multiply n by fact5, -n 1. So here, we saw in fact4 we had two few parentheses. It made us annoyed, we just wanted to get our homework done, so we added some more. The problem, of course, is this still works, but we added too many. And what it says is, procedure fact5: expects 1 argument, given 0. That's exactly right, right here I'm calling fact5 with zero arguments. fact5, which I'm defining recursively right here, expects one argument. You are not allowed to call functions with the wrong number of arguments, and we get an error, okay? And then let's do one last one, just because it's good practice. N times, so this is a very natural thing to do because we've all grown accustomed to writing arithmetic a certain way. And you can probably see the error this time. I wrote star after second, that's supposed to be the function I'm calling. Instead, what do you think would happen here? Well, again, this base case is fine. But if n is not 0, then I'm going to try to treat n as a function. So I would expect some sort of error message where the number I call fact6 with is trying to be called with some arguments, right? When you look at your code carefully, you can sometimes come up with a better error message than you would get from a system that has no idea of what you're trying to do. Here I think it'll actually do a pretty good job, says, procedure application: expected procedure, given 1: arguments were: procedure times 1. And what actually happened is, you would think this happen when n would be 5, why does it say, given 5? Well, it never got to this call, it went ahead and did the recursion, and that did the recursion, and that did the recursion. And it's on the way back out of the recursion that it first detects the error. When it tries to say 1 times, and the recursive result 1. And if, and we'll write this out in Racket. You have 1 times 1, that's going to give the exact same error message. Because it's going to say it expected a procedure in that first position, and you have a 1.