If you've ever played 20 Questions, you know that the answer to true/false
questions can really say a lot. And in fact, in computer programs,
true/false questions turn out to be fundamental.
In this video, what I want to do is talk about a new kind of value called the
Boolean that's going to represent the answer to true/false questions.
I'm also going to talk about a number of primitive true/false questions and a new
expression in Racket called if that's going to let us make our programs produce
different values depending on the answer to true/false questions.
Boolean values are going to represent the answer to true false questions.
So you shouldn't be surprised to find that there's two Boolean values, and in
the beginning student language, we write them this way: true if the value that
represents the true answer to a true/false question and false is the
value that represents a false answer and since their values if we run them if we
evaluate them we get the value themselves.
Okay, let me comment those out. How we're going to represent the answer
one of the questions. Now, let me just set myself up here a
bit, I'll give myself two constants, width and height.
I'll just make them both be a 100. Okay?
So here is a true/false question. Here's a primitive called greater than.
And if we say greater than width, height, and evaluate that, run that, we get
false. Because width is 100, height is 100, and
100 isn't greater than 100. On the other hand, here's another
primitive. Greater than or equal width, height, and
if we run that now, we get false for the first one and true for the second one,
because 100 is greater than or equal to 100.
These kinds of primitives that produce a true/false value are often called
predicates, so we would say that greater than is a predicate, and greater than or
equal to is a predicate. And, there's lot of others.
You could say equals 1 2 or equals 1 1. Let me just comment these two outs so
they don't confuse us. Or, greater than 3 9.
And we'll run that. And equals 1 2 is giving us false.
Equals 1 1 is giving us true. And, or, rather greater, than 3 9 is
giving us false. And there's lots of others and I'll
remind you that the 1x lecture video will show you how to discover more.
Let me just show you a couple more. I'll comment this out now so it doesn't
confuse us. There's some that operate on strings.
So, for example, you could say string equals question mark foo bar.
And that's false, because those two strings are not equal.
What if I were to ask questions about images, so let's see, suppose I want to
have two images like this. I1 is a rectangle that's 10 by 20 and
it's solid and it's red and I2 is a rectangle and it's 20 by 10 and it's
solid and it's blue. Suppose I want to know which image is
thinner, I could say less than image with I1 image width I2, and I could run that.
Oh, let's see, rectangle, this function is not defined oh, this is the usual
mistake, wanted to use image functions and I forgot to put a required.
I'll just go put require 2htdp/image. And now, if I run this, I'm getting true,
meaning that the width of I1 which is 10 is less than the width of I2 which is 20.
Okay, so that's Boolean values true and false.
And, a number of predicates that are questions that produce true/false
answers. Now I want to talk about if expression,
which are going to let us have our program produce different results,
depending on the answer to true false questions, depending on the result
produced by a predicate. If expressions are simple to form.
It's open paren, if and then three expressions, and a closed paren.
We call those three expressions the question, the true answer and the false
answer. And one key thing is that the question
expression has to produce the boolean value, so the question expression usually
calls a predicate of some form. Now, let's look at an example.
Going back to where we were, let me start by just deleting this expression here,
and then, we'll try to write an if expression that determines what the shape
is of I1. So we'll say open paren if, and then,
let's say, less than is the width of I1 less than height of I1.
And if that's true, that's the question. If the question is true, then here is the
true answer. We're going to say that the image is tall
if its width is less than its height and in the tall sense, we'll say that the
image is wide. And if I run that now, there's two
interesting things to see here. One is that the result was tall, because
sure enough I1 is taller than it is wide, and the other interesting thing to see
was that right here, this piece of code was highlighted in black.
Depending on which version of Racket you're using, it might be highlighted in
orange, but it's highlighted. We're going to talk a lot more about that
later this week. But if I go ahead now and switch around,
maybe I ask the question about I2 instead of I1, well, I2's width is greater than
its height. And in this case, if we evaluate the
expression, it produces wide and the other, the true answer this time is
highlighted in black. So, you may be able to start to guess
what that black highlighting means, but again, we'll talk about that later.
So, that's an example of an if expression.
What we need to do now is look at the detailed rules for evaluating if
expressions. What I'm going to do is first go ahead
and put the evaluation rules for if here on the right, and then, I'm going to
change the example expression a little bit, just to make it a little bit richer
so we'll understand the rules of it better.
I'll say that if the width is less than the height will produce the width.
That, the true answer will be the width and the false answer will be the height.
Now, let's try to step through that bit by bit.
And I'll also use the Ctrl+E or Command+E command to just make it rank the high the
[UNKNOWN]. So I've got a bit more room to work.
So let's see, I've got an if expression. And the rule for evaluating an if
expression is the first thing I have to do is evaluate the question expression.
So there's the question expression, the question expression is a call to the
primitive less than. So the first thing I have to do is reduce
all of its operands to values. Let's see, the first operand isn't a
value, it's an expression. In particular, it's a call to the
primitive image width, and the first thing I have to do is reduce all of its
operands to values. G, this first operand isn't a value, it's
the name of a constant. So I have to produce a value for red.
So, the first evaluation step [SOUND] simply is going to reduce that
expression, the constant name, to the corresponding value.
In this case, what that does is that I2, it comes the actual image, image value.
Okay, so now let's see. If expression reduced the question,
reduced the operands to this last stand. Here's the first operand that's imaged
with that uh-huh. What happens here is that this whole
thing, I'm just copying it and pasting it.
This whole thing, we just end up reducing this expression here this time.
So that's going to become 20, the width of rectangle 2.
The next step, well, at this point, I think you could see how this is going to
work. Now, we're basically reducing this
operand to the last then. In the next step, the I2 becomes an
image. And then, in the step after that, that
whole thing becomes 10. And I'll just put it on one line like
this so we get a bit more room to work with.
So remember, what we did here is we had to evaluate the if expression, if wants
to evaluate its question expression first.
This was a call to a primitive, in which both oeprands as calls to primitive.
So there's a fair amount of evaluation work we have to do here before we've
evaluated the question expression, and we still aren't even done, we still have a
call to a primitive. Both operands are values, so now, we can
actually call less than with the two values.
Now, less than, now less than 20 10, well, 20 is not less than 10.
So that's clearly going to be false. And now, finally, we've evaluated the
question expression. We evaluated the question expression, and
now, we go to the remaining rules of the if.
Next rule say's that if the question expression produces true.
Well, it hasn't. Here, the question expression has
produced false. So the next rule say's if the question
expression produces false. Then what we're going to do is replace
the entire if expression with the false answer, so there is the false answer, the
entire expression gets replaced with a false answer.
Now we have a call to a primitive, first operand is not a value so we need to
evaluate it. So that has to get evaluated.
Now, all the operand statement type are values so we can actually call image
height and we get 10, and that's going, the whole thing evaluates to 10.
And again, if we use that trick I showed you in the last video of running this,
now, we'll see a whole bunch of 10s, which tells us that we did all of our
evaluation steps properly. So the key thing is the rule for if is
first you evaluate the question, and then depending on the results of the question,
you replace the entire if with either the true answer or the false answer and then
you just keep evaluating. What I want to do now is back up just a
little bit. Let's go back to when we just had image 1
and image 2. And we know that if we want to find out
whether image 1 has a height greater than image 2, we could say this.
So that's comparing the height of I1 and the height of I2, and if we run that,
we'll get true because 20 is bigger than 10.
We can also, if we wanted to compare the width of I1 and the width of I2 to see,
in some sense, this first thing is saying is I1 taller than I2 and the second one
is saying is I1 skinnier than I2? And that's true.
Now, what if we wanted to know whether I1 was both taller and skinnier than I2?
If it was both things together. Well, here's a new primitive called and,
and is a special kind of expression like if.
And the way and works is you can wrap open paren around any number of other
expressions that themselves are going to produce a Boolean value.
And what and does is it evaluates the first one, and if that one produces true
it keeps going. And if by the time it gets to the end all
of the expressions have produced true, then the whole and produces true.
If on the other hand and gets to an expression that produces false, then it
stops right away and produces false. So and does what's called short
circuiting. It doesn't keep evaluating if it comes to
an expression that produces false. It only keeps going as long as the
expressions are producing true. There's also a primitive or expression
and there's a primitive function called not.
You can look both of those up in the help desk and you can watch this Week's I1
video to find out how to use the help desk.