Here's another How To Design Functions problem.
And again, it elaborates on the problem we saw before.
What I'm going to do in this problem is, when I start out, I'm not going to choose
the best signature, and then we'll fix it later.
And the reason I'm doing that is I want to illustrate to you that the how to
design functions recipe is not intended to be what's called a waterfall process.
It's not intended to be something that you do the first step and then the second
step and then the third step and absolutely get each step right.
It happens pretty often. That you go through the recipe and you
get to kind of the third or the fourth step and maybe you realize oh the
signature is not exactly right and you go back and fix it.
And sometimes what even happens is you skip a first step to get to a later step
just to get started. A common example is you're not quite sure
about the signature. So you go write some examples and then
you come back and do the signature. Now what I don't want to do is give you
Carte blanche to jump immediately to the function definition and do that.
That's not going to be what we call systematic design.
But I also don't want you to feel like gee I just don't know what the signature
is but I'm not allowed to do anything else until I write it.
There is some flexibility in following the steps of the process.
It's a structured process but it's not a locked in waterfall process.
So here we go. Let's do this example.
In this problem we're going to design a function called image area that consumes
an image and produces the area of that image.
And it says for area we just need to multiply the image's width by it's
height. So let's see, this function consumes an
image and it produces the area of the image.
Now, you might think this should be number and that's actually going to turn
out not to be actually right, but I'm going to go ahead and pretend that I put
number for now, because one of the things I want to show is that sometimes you
realize, part way through the process, that a piece of what you did before isn't
right. So I'm just going to put number for now.
Then I'm going to say produce image's width times height for area.
Let's see, the stop is going to be define.
Image area what I like to abbreviate image to img and a good dummy value is
zero because its a number and now let's do some examples.
Check expect image area. let's say I have a rectangle that's 2
wide and 3 high and that it's just red. What's the area of that?
Well, the area of that is times 2 3. Alright, let's run that test to see if
it's well formed. oh, rectangle is not defined.
Oh, that's because whenever we use image functions, we need to tell Dr.
Racket that we want to use the image function, and I forgot to do that.
So, we're going to say require 2htvp image.
This is a very common mistake, and I made it here on purpose so that you would see
it happen. You just forget to do the require.
Now, that we've done the require, the test is actually running and failing but,
it's running. So, we're doing reasonably well.
Let's keep going here. Define image area.
So, that's the stub, we'll label it as that.
We'll do the template which will be dot, dot, dot, img.
Now, we'll make a copy of the template. We'll comment out the original template
and label it. And now what's this going to be its gotta
be the images width we're going to use image twice because we need its width and
its height. So, we're going to use image twice.
We're going to say image, width of the image and image height of the image and
we're going to multiply those two together.
Now, let's run that. And the test passed.
But now, we might realize this interesting thing, which is that images
are always sized in pixels, and pixels are, are, are always a natural number, 0,
1, 2, 3, 4, 5, something like that. You can't have 3.2 pixels, that's not how
pixels are. So, if the width is always going to be a
natural, and the height is always going to be a natural, and you multiply
those two, this actually could be natural instead of the number.
And one of the things that we're going to talk about a lot in the course is that
when you write the signature for a function, you always want to use the most
specific types That are correct. Turns out it makes it much easier to
think about using the function and to debug programs if you use the most
specific correct type. So in this case, this function was never
going to produce a floating point number like 3.2.
It's always going to produce a natural. So we take the trouble to make the
signature say that. And I'll save that file and run it one
last time. The test passed.