* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Download CSE_341_Unit_01_Func..
C Sharp syntax wikipedia , lookup
Functional programming wikipedia , lookup
Go (programming language) wikipedia , lookup
Dirac delta function wikipedia , lookup
Corecursion wikipedia , lookup
APL syntax and symbols wikipedia , lookup
Recursion (computer science) wikipedia , lookup
CSE_341_Unit_01_Functions_Informally [00:00:00.00] [00:00:05.38] OK, in this segment we're going to start studying functions. These are a new kind of binding. So we're going to change our definition of program to not just be a sequence of variable bindings, but to allow both variables and functions. [00:00:18.83] If you haven't heard of the term function, it's a lot like a method in an object oriented language. This is something that's going to take arguments, compute some result, and return that result. That's all it does. So it's in many ways, simpler than a method, and we're always going to call these things functions. [00:00:35.09] So why don't I just flip over to [? EMax ?] here and show you a first example. How about I write a little function for exponentiation or raising something to the power of something else? So here is most of what I need to write. OK, so I have the keyword fun, the name of the function I'm defining, pow, the arguments it takes. Here, x and y, separated by commas. I've written their types with a colon and then the type name. Then an equals and then I have my function body. [00:01:07.54] OK, so that body can just be any expression I want and what happens when you call the function, it is we are going to evaluate that expression, and then the result will be the result of the function. So for exponentiation, what I want is something like a conditional expression that says if y is 0, than 1. [00:01:26.89] Otherwise, how about x times this other expression, which is to call the pow function with x and y minus 1. And that will work as long as y is greater than or equal to zero. And I'll make no attempt to be correct for negative y, since this is just an example. [00:01:46.67] So this is a program. This can be included in my sequence of bindings. I could have a val binding before. Maybe afterwards I could have another function binding. How about something that takes its argument and cubes it? So I could define this as x times x times x, or I could use any previous bindings, since it'll be in my environment, and I could instead implement this as pow(x,3). [00:02:11.08] So the body of this cube function is itself a function call that calls pow with x, which is the argument to cube, and the constant 3. So I could use these functions. I could say val sixtyfour. That should just equal cube of 4. You don't actually need these parentheses, but it looks a little more like other languages if I put them in, at least for now. Or I could have something that uses more nested expressions. [00:02:40.75] You can call a function with an expression, in which case I'll evaluate this 2 plus 2 to 4, and then pass 4 as the second argument to pow. Here, I could add another 16, and another 8, and another 2. You could even have nested calls if you wanted. So you could say pow(2,2) in there, and so on. [00:03:04.42] When you want to test something out, just like always, go over here to the REPL. We can say use "functions.sml". See all of our bindings there? You'll notice that pow and cube print differently than variable bindings. In terms of the value, they just say I'm a function. We don't print out the body of the function or anything. The REPL will always just say, here is a function, and here is it's type. [00:03:30.25] So you see with pow that it has type int star int arrow int. So the way function types are written in ML is we write down the types of the arguments separated by a star. So it takes two int arguments, int star int, and then a hyphen, and angle bracket, and arrow, and then the result type, which is an int. [00:03:54.28] Notice we didn't have to write down that result type. ML figured it out by looking at the function body, that conditional that we had up here, and realizing that if x and y have type int, the conditional have type int. And so, the function when called with two ints, will return an int. Similarly, cube is a function that takes one int and returns one int. 64 and 42 are as usual and we can try things out at the REPL now. So we could cube 7, and we would get 343, and so on. [00:04:27.65] So that's the informal idea of functions. Let me make a few points here back with the slides, since this is a new thing we're learning. The first thing is that the body of the pow function, itself, can use pow. So that's how we implement recursive algorithms, as we did here. So all this is showing is that inside a function body, you can call the function itself. [00:04:51.46] There's a few gotchas when you start writing things out. We have all the sources of potential error messages, especially if you leave that colon off between the name of the variable and the type, or if like in other languages, you try to write int x instead of x colon int. All of these things are syntax errors and you're going to get error messages as a result. [00:05:11.02] I would also point out that when we wrote out those function types in the REPL, we saw that pow had type int star int arrow int. That star is different than the star for multiplication. So it's just a reuse of the same character. In expressions, star means multiply. In types, at least as we've seen so far, it's just separating the types of multiple arguments. [00:05:36.32] And finally, just like variable bindings, function bindings can use earlier bindings in the file, but they can't use later bindings in the file, and that's again, just ML's rule. So any helper functions you want, if you want to define one function like cube, in terms of another function like pow, then you have to put cube second. Now, this does raise an interesting question. What if you had two or three functions that all wanted to call each other? There would be no good order to put them in and I'll show you in some future segments some special support in ML for that case of mutual recursion. [00:06:10.51] If you're not yet comfortable with recursion, hopefully you've at least seen it before. You will be soon. On the first homework assignment, pretty much every function you write will be recursive, and we're going to see a bunch more examples. So don't panic if the algorithm for pow looked a little too magical, but there's really absolutely nothing magical to it. [00:06:30.25] So let me flip back here and just show you this pow function. The reason why we can define pow in terms of pow, there's nothing circular here. What we did is we defined raising something to the yth power in terms of raising something to the y minus 1th power, and that is a perfectly reasonable definition. A recursive call is solving a simpler problem, and if that simpler problem is that y is zero, then we don't use recursion at all, and we just returned the answer one. So we'll get very comfortable with this idea as we move forward. [00:07:02.89] And in ML we're always going to use recursion for these sorts of things. If you're used to writing things like pow with while loops or for loops, we're not going to use them. They often obscure what are simpler, more elegant algorithms, and recursion is more powerful. So often, while loops and for loops are more convenient, or the idiom in many programming languages. [00:07:25.09] In many programming languages, they're more efficient, but anything you can do with a loop, I promise you, you can do with recursion. And we're going to focus on that approach in ML. And really most of the programming we do in the class.