In this video, I'm going to talk about functions.
Functions are the mechanism in the beginning student language that's going
to let you write programs that let you produce a different value each time they
run. Right now our programs are always
producing the same value. So functions are incredibly important and
powerful, and they're going to form the bulk of our programs.
But I think what you're going to see here in a few minutes is that in the beginning
student language, functions are not too difficult to learn.
We're starting to be able to build up some interesting results.
For example, here, by using above and circle three times, I can write an
expression which when I run it, produces this little traffic light or at least
it's sort of like a North American traffic light except that too many lights
are on. Well let's look at this expression a bit.
It's easy to be bothered by the amount of redundancy in it.
Notice that in this expression, all of these parts are unchanging in the three
calls to circle. These parts are unchanging.
Only this part here is changing in each of the calls to circle.
And it's easy to be worried, gosh, if programs get big, and a lot of them are
sort of duplicated code like this That, that seems needless.
That seems like it's going to be cumbersome, and it would be cumbersome,
and it is needless. There's a mechanism that's going to let
us prevent that called function definitions.
So, what are function definitions, and how do they work?
Well, you actually already understand a lot about function definitions.
You just have to remember your grade school math in which you learned that you
could write mathematical functions like this.
For example, here is f of x. It equals 2 times x, and that means that
f of 2, is 2 times 2, is 4, or f of 6, is 2 times 6, is 12.
What's going on in these function definitions is that x, which is called
the parameter, stands for the varying value.
And then, the rest of the function definition is the unchanging value, the 2
times in this case. And then the function can be used any
number of times with a different value each time, or even in sometimes, it can
be used with the same value as before. And each time the parameter will take on
the changing value and you get the result of the function with that value.
So how's this going to work for us. The beginning of student language has a
function definition mechanism, and it works like this.
I'm going to write define, open parentheses, the name of a function.
In our functions, we're not going to have to use th-, single-character names likes
x. I'm going to call this function bulb, and
the name of a parameter, which in this case, I'll call: c.
And then I'm going to write that the body of the function is: (circle 40 "solid",
and then: c. What's going to happen here, just like in
the mathematical functions, is that the parameter C is going to stand for the
changing value. And then the body of the function is
going to use that parameter in the place where it wants to use the changing value.
And now I can show you how this function works if I write open paren bulb and then
say purple. This is a call to the function.
Intuitively you could think of it that the body of the function was evaluated
With C taking on the changing values. So with C taking on the value purple.
In a minute, I'll show you the exact evaluation rules, but for now you can
think of it intuitively that way. Now that I have the bulb function, I can
clean this up some. Let me just take this whole thing, and
for now, I'll just comment it out. I'm going to get rid of this bulb purple,
because that one's just for demonstration, and I'll rewrite the
original expression we had this way. And then when I run the program, I get
the same result as before. Now, this expression, at the end, is much
more concise than the original expression.
It reduces the duplication And that's what makes it more concise.
And also by choosing a nice name here, by choosing the name bulb, I give the code a
bit more meaning. I can now think of these as three bulbs,
one atop the other. And what we do now in a real program is
we go ahead and completely get rid of this plummeted-out stuff.
And just because I think it looks better because These bulbs are one on top the
other. I would probably format this above that
way. And now I've got something that's nice
and concise and it's clear for me to understand what it's doing.
What I want to do now is the same thing we've done with all the other beginnings
student language constructs we've seen, which is to go over in a little bit more
detail the rules for forming function definitions and function calls and also
the rules for evaluating function calls. Before I get to those rules, I just want
to show you something which is where you could find all of the rules for the VSL
language. If you go to the course web page and you
scroll here to the languages tab, then this page has all the rules for the BSL
language including how to form all the kinds of expressions we've seen and the
rules for evaluating them and so on. The rule for forming a function
definition is simple. You start with open paren define because
it's a definition. And then we have open paren and the name
of the function, followed by the names of the parameters.
In the example we have so far we just have one parameter, c.
But we'll define other functions later that have more than one parameter, and
then we close that paren so this first part has open paren the name of the
function the name of the parameters, then we close that, that paren.
And then we always put it on a new line. We have an expression which forms the
body of the function. So here's the example we've seen so far,
define, the name of the function is bulb, the parameter is C and here's the body of
the function. To form a function call expression, we
put open paren, the name of a defined function, and then we put some number of
expressions corresponding to the number of parameters the function has.
So for our bulb function, which has a single parameter, we put a single
expression after the bulb name. And those expressions are all called
operands. To show you how the rules for evaluation
related to functions work, you're going to first start by getting a
somewhat simpler example. What I've got here is a call to bulb
where its argument, instead of already being a value is going to be another
call, a primitive call. And I'm mostly going to set up by putting
the Rules for evaluating functions and permitive calls here on the right.
So let's see, we look at open paren bulb, and that tells us that we've got a
function call. So the rule for evaluating function call
is to first reduce the operands to values.
So now let's go look at the first operand.
First operand is open paren string append, so that's a primative call.
So, we now look at the rules for evaluating a primitive call.
And the first rule is to reduce operands to values again.
Notice that the rule, the first rule for function calls and operand, primitive
calls is the same, you reduce the operands to values.
Well, let's see. RR, the string re and the string Stream D
are both already values, so now we can apply the string of pan primitive.
And the first full step in the evaluation is that we now have bulb with an operand
of the value web. So now going back to the function call
roles, we have now reduced the first operand to a value.
We would, so we reduce all operands to a value, and now we're going to replace the
function call by the body of the function.
So I've copied the body of function down here, but in the body of function, we're
going to replace every reoccurrence of the parameter c by the argument, the
corresponding argument to the function in this case, red.
And now what do we have? Well, open paren circle, this is a call
to a primitive. So notice the function call is completely
gone now, once we've replaced the call with its body, we just work on evaluating
the replaced body. This is a call to a primitive.
The first rule for a primitive is to reduce all the operands to values.
There's three operands, in this case, and they are all already values.
So now the second step of a call to a primitive is to just apply the primitive
to the values. And the value of that primitive call is a
red circle. And now all we've got is a value, so
evaluation stops. Let me just point one thing out to you
about the way I've done this and step by step evaluation.
By writing all the different steps to the evaluation in the definitions window,
this way, what I can do now is actually run this.
And since there's four steps to the evaluation- I should see the same result
four times because when rackets starts here and runs to the end, it gets a red
circle. When it starts here and runs to the end,
it gets a red circle. When it starts here and runs to the end,
it gets a red circle. And when it starts with a red circle and
runs to the end, it gets a red circle. So if you do your step-by-step evaluation
exercises, in the definitions window, like this, and then run it, you can kind
of check whether you've got the right step by step evaluation because you
should see the same value repeated each time.
Now you understand how to define functions, and you know the rules for
evaluating function calls. As I said at the beginning, functions are
going to be incredibly important to all of our racket programs.
So it's really important that you understand how they work.
So if it's ever unclear to you, just come back to this video, and also be sure to
work the practice problems that are associated with this video.
Just as an aside, so you understand how powerful functions are, one of the most
important theoretical results in computer science says that if you have a language
that just has functions, just functions, no strings, no numbers, just functions,
you can actually write any program that can be written in any language.
Now, you know that's a theoretical result that makes academics happy.
A language like that would be pretty cumbersome to program in, so you would
never do it. Back in practical terms now we want
functions, we want strings, we want images, we want numbers, we want all of
that. Even so, functions are pretty essential
to the whole game.