WEBVTT

00:00:03.880 --> 00:00:14.550
[MUSIC PLAYING]

00:00:14.550 --> 00:00:15.790
PROFESSOR: I'd like to
welcome you to this

00:00:15.790 --> 00:00:17.270
course on computer science.

00:00:28.370 --> 00:00:29.990
Actually, that's a terrible
way to start.

00:00:29.990 --> 00:00:32.740
Computer science is a terrible
name for this business.

00:00:32.740 --> 00:00:35.572
First of all, it's
not a science.

00:00:35.572 --> 00:00:40.300
It might be engineering or it
might be art, but we'll

00:00:40.300 --> 00:00:43.470
actually see that computer
so-called science actually has

00:00:43.470 --> 00:00:45.350
a lot in common with magic,
and we'll see

00:00:45.350 --> 00:00:47.210
that in this course.

00:00:47.210 --> 00:00:48.040
So it's not a science.

00:00:48.040 --> 00:00:53.340
It's also not really very
much about computers.

00:00:53.340 --> 00:00:57.140
And it's not about computers in
the same sense that physics

00:00:57.140 --> 00:01:02.920
is not really about particle
accelerators, and biology is

00:01:02.920 --> 00:01:06.350
not really about microscopes
and petri dishes.

00:01:06.350 --> 00:01:10.400
And it's not about computers
in the same sense that

00:01:10.400 --> 00:01:16.480
geometry is not really about
using surveying instruments.

00:01:16.480 --> 00:01:20.320
In fact, there's a lot of
commonality between computer

00:01:20.320 --> 00:01:21.240
science and geometry.

00:01:21.240 --> 00:01:23.830
Geometry, first of all,
is another subject

00:01:23.830 --> 00:01:25.680
with a lousy name.

00:01:25.680 --> 00:01:28.130
The name comes from Gaia,
meaning the Earth, and metron,

00:01:28.130 --> 00:01:29.770
meaning to measure.

00:01:29.770 --> 00:01:31.350
Geometry originally
meant measuring

00:01:31.350 --> 00:01:34.260
the Earth or surveying.

00:01:34.260 --> 00:01:37.260
And the reason for that was
that, thousands of years ago,

00:01:37.260 --> 00:01:40.930
the Egyptian priesthood
developed the rudiments of

00:01:40.930 --> 00:01:45.320
geometry in order to figure
out how to restore the

00:01:45.320 --> 00:01:47.430
boundaries of fields that were
destroyed in the annual

00:01:47.430 --> 00:01:49.390
flooding of the Nile.

00:01:49.390 --> 00:01:52.360
And to the Egyptians who did
that, geometry really was the

00:01:52.360 --> 00:01:55.600
use of surveying instruments.

00:01:55.600 --> 00:01:57.850
Now, the reason that we think
computer science is about

00:01:57.850 --> 00:02:01.770
computers is pretty much the
same reason that the Egyptians

00:02:01.770 --> 00:02:04.520
thought geometry was about
surveying instruments.

00:02:04.520 --> 00:02:07.340
And that is, when some field
is just getting started and

00:02:07.340 --> 00:02:11.790
you don't really understand it
very well, it's very easy to

00:02:11.790 --> 00:02:15.280
confuse the essence of what
you're doing with the tools

00:02:15.280 --> 00:02:17.590
that you use.

00:02:17.590 --> 00:02:20.960
And indeed, on some absolute
scale of things, we probably

00:02:20.960 --> 00:02:25.100
know less about the essence of
computer science than the

00:02:25.100 --> 00:02:26.955
ancient Egyptians really
knew about geometry.

00:02:29.970 --> 00:02:32.570
Well, what do I mean by the
essence of computer science?

00:02:32.570 --> 00:02:34.300
What do I mean by the
essence of geometry?

00:02:34.300 --> 00:02:36.380
See, it's certainly true that
these Egyptians went off and

00:02:36.380 --> 00:02:40.190
used surveying instruments, but
when we look back on them

00:02:40.190 --> 00:02:42.240
after a couple of thousand
years, we say, gee, what they

00:02:42.240 --> 00:02:45.910
were doing, the important stuff
they were doing, was to

00:02:45.910 --> 00:02:52.510
begin to formalize notions about
space and time, to start

00:02:52.510 --> 00:02:57.490
a way of talking about
mathematical truths formally.

00:02:57.490 --> 00:02:59.420
That led to the axiomatic
method.

00:02:59.420 --> 00:03:04.420
That led to sort of all of
modern mathematics, figuring

00:03:04.420 --> 00:03:08.350
out a way to talk precisely
about so-called declarative

00:03:08.350 --> 00:03:10.000
knowledge, what is true.

00:03:12.550 --> 00:03:15.680
Well, similarly, I think in the
future people will look

00:03:15.680 --> 00:03:18.520
back and say, yes, those
primitives in the 20th century

00:03:18.520 --> 00:03:20.190
were fiddling around with
these gadgets called

00:03:20.190 --> 00:03:25.790
computers, but really what they
were doing is starting to

00:03:25.790 --> 00:03:32.730
learn how to formalize
intuitions about process, how

00:03:32.730 --> 00:03:47.100
to do things, starting to
develop a way to talk

00:03:47.100 --> 00:03:52.190
precisely about how-to
knowledge, as opposed to

00:03:52.190 --> 00:03:56.470
geometry that talks about
what is true.

00:03:56.470 --> 00:03:57.810
Let me give you an
example of that.

00:04:01.650 --> 00:04:02.550
Let's take a look.

00:04:02.550 --> 00:04:08.250
Here is a piece of mathematics
that says what

00:04:08.250 --> 00:04:10.250
a square root is.

00:04:10.250 --> 00:04:17.019
The square root of X is the
number Y, such that Y squared

00:04:17.019 --> 00:04:20.290
is equal to X and Y
is greater than 0.

00:04:20.290 --> 00:04:23.510
Now, that's a fine piece of
mathematics, but just telling

00:04:23.510 --> 00:04:26.900
you what a square root is
doesn't really say anything

00:04:26.900 --> 00:04:31.420
about how you might go
out and find one.

00:04:31.420 --> 00:04:37.410
So let's contrast that with a
piece of imperative knowledge,

00:04:37.410 --> 00:04:39.840
how you might go out and
find a square root.

00:04:39.840 --> 00:04:44.660
This, in fact, also comes
from Egypt, not

00:04:44.660 --> 00:04:45.640
ancient, ancient Egypt.

00:04:45.640 --> 00:04:50.050
This is an algorithm due to
Heron of Alexandria, called

00:04:50.050 --> 00:04:52.910
how to find a square root
by successive averaging.

00:04:52.910 --> 00:05:03.370
And what it says is that, in
order to find a square root,

00:05:03.370 --> 00:05:07.560
you make a guess, you
improve that guess--

00:05:10.070 --> 00:05:12.670
and the way you improve the
guess is to average the guess

00:05:12.670 --> 00:05:15.170
and X over the guess, and we'll
talk a little bit later

00:05:15.170 --> 00:05:17.080
about why that's a reasonable
thing--

00:05:17.080 --> 00:05:19.740
and you keep improving the guess
until it's good enough.

00:05:19.740 --> 00:05:20.800
That's a method.

00:05:20.800 --> 00:05:25.070
That's how to do something
as opposed to declarative

00:05:25.070 --> 00:05:28.270
knowledge that says what
you're looking for.

00:05:28.270 --> 00:05:29.520
That's a process.

00:05:34.130 --> 00:05:38.850
Well, what's a process
in general?

00:05:38.850 --> 00:05:40.000
It's kind of hard to say.

00:05:40.000 --> 00:05:45.350
You can think of it as like a
magical spirit that sort of

00:05:45.350 --> 00:05:47.870
lives in the computer
and does something.

00:05:47.870 --> 00:05:56.250
And the thing that directs a
process is a pattern of rules

00:05:56.250 --> 00:05:57.500
called a procedure.

00:06:01.690 --> 00:06:05.940
So procedures are the spells,
if you like, that control

00:06:05.940 --> 00:06:10.700
these magical spirits that
are the processes.

00:06:10.700 --> 00:06:12.650
I guess you know everyone needs
a magical language, and

00:06:12.650 --> 00:06:17.310
sorcerers, real sorcerers, use
ancient Arcadian or Sumerian

00:06:17.310 --> 00:06:18.670
or Babylonian or whatever.

00:06:18.670 --> 00:06:21.540
We're going to conjure our
spirits in a magical language

00:06:21.540 --> 00:06:26.750
called Lisp, which is a language
designed for talking

00:06:26.750 --> 00:06:31.120
about, for casting the spells
that are procedures to direct

00:06:31.120 --> 00:06:32.040
the processes.

00:06:32.040 --> 00:06:33.780
Now, it's very easy
to learn Lisp.

00:06:33.780 --> 00:06:35.810
In fact, in a few minutes,
I'm going to teach you,

00:06:35.810 --> 00:06:36.960
essentially, all of Lisp.

00:06:36.960 --> 00:06:40.660
I'm going to teach you,
essentially, all of the rules.

00:06:40.660 --> 00:06:43.440
And you shouldn't find that
particularly surprising.

00:06:43.440 --> 00:06:46.150
That's sort of like saying it's
very easy to learn the

00:06:46.150 --> 00:06:46.940
rules of chess.

00:06:46.940 --> 00:06:48.860
And indeed, in a few minutes,
you can tell somebody the

00:06:48.860 --> 00:06:50.710
rules of chess.

00:06:50.710 --> 00:06:53.490
But of course, that's very
different from saying you

00:06:53.490 --> 00:06:55.740
understand the implications of
those rules and how to use

00:06:55.740 --> 00:06:58.420
those rules to become a
masterful chess player.

00:06:58.420 --> 00:07:00.380
Well, Lisp is the same way.

00:07:00.380 --> 00:07:02.610
We're going to state the rules
in a few minutes, and it'll be

00:07:02.610 --> 00:07:03.360
very easy to see.

00:07:03.360 --> 00:07:06.210
But what's really hard is going
to be the implications

00:07:06.210 --> 00:07:09.310
of those rules, how you exploit
those rules to be a

00:07:09.310 --> 00:07:12.080
master programmer.

00:07:12.080 --> 00:07:15.260
And the implications of those
rules are going to take us

00:07:15.260 --> 00:07:17.770
the, well, the whole rest of
the subject and, of course,

00:07:17.770 --> 00:07:19.020
way beyond.

00:07:21.420 --> 00:07:26.070
OK, so in computer science,
we're in the business of

00:07:26.070 --> 00:07:30.910
formalizing this sort of how-to
imperative knowledge,

00:07:30.910 --> 00:07:33.330
how to do stuff.

00:07:33.330 --> 00:07:35.120
And the real issues of computer
science are, of

00:07:35.120 --> 00:07:38.620
course, not telling people
how to do square roots.

00:07:38.620 --> 00:07:40.050
Because if that was
all it was, there

00:07:40.050 --> 00:07:41.760
wouldn't be no big deal.

00:07:41.760 --> 00:07:45.550
The real problems come when we
try to build very, very large

00:07:45.550 --> 00:07:49.270
systems, computer programs that
are thousands of pages

00:07:49.270 --> 00:07:52.640
long, so long that nobody can
really hold them in their

00:07:52.640 --> 00:07:54.640
heads all at once.

00:07:54.640 --> 00:07:58.770
And the only reason that that's
possible is because

00:07:58.770 --> 00:08:17.830
there are techniques for
controlling the complexity of

00:08:17.830 --> 00:08:21.590
these large systems. And these
techniques that are

00:08:21.590 --> 00:08:22.950
controlling complexity
are what this

00:08:22.950 --> 00:08:24.700
course is really about.

00:08:24.700 --> 00:08:26.030
And in some sense, that's
really what

00:08:26.030 --> 00:08:29.650
computer science is about.

00:08:29.650 --> 00:08:31.740
Now, that may seem like a very
strange thing to say.

00:08:31.740 --> 00:08:34.960
Because after all, a lot of
people besides computer

00:08:34.960 --> 00:08:37.970
scientists deal with controlling
complexity.

00:08:37.970 --> 00:08:41.860
A large airliner is an extremely
complex system, and

00:08:41.860 --> 00:08:44.760
the aeronautical engineers who
design that are dealing with

00:08:44.760 --> 00:08:47.030
immense complexity.

00:08:47.030 --> 00:08:49.380
But there's a difference
between that kind of

00:08:49.380 --> 00:08:52.205
complexity and what we deal
with in computer science.

00:08:55.090 --> 00:08:57.750
And that is that computer
science, in some

00:08:57.750 --> 00:08:59.700
sense, isn't real.

00:09:02.670 --> 00:09:07.070
You see, when an engineer is
designing a physical system,

00:09:07.070 --> 00:09:09.520
that's made out of real parts.

00:09:09.520 --> 00:09:12.820
The engineers who worry about
that have to address problems

00:09:12.820 --> 00:09:16.540
of tolerance and approximation
and noise in the system.

00:09:16.540 --> 00:09:19.280
So for example, as an electrical
engineer, I can go

00:09:19.280 --> 00:09:21.885
off and easily build a one-stage
amplifier or a

00:09:21.885 --> 00:09:25.090
two-stage amplifier, and I can
imagine cascading a lot of

00:09:25.090 --> 00:09:26.760
them to build a million-stage
amplifier.

00:09:26.760 --> 00:09:30.900
But it's ridiculous to build
such a thing, because long

00:09:30.900 --> 00:09:33.160
before the millionth stage,
the thermal noise in those

00:09:33.160 --> 00:09:34.740
components way at the beginning
is going to get

00:09:34.740 --> 00:09:36.200
amplified and make the whole
thing meaningless.

00:09:38.880 --> 00:09:44.070
Computer science deals with
idealized components.

00:09:44.070 --> 00:09:47.430
We know as much as we want about
these little program and

00:09:47.430 --> 00:09:51.820
data pieces that we're fitting
things together.

00:09:51.820 --> 00:09:53.090
We don't have to worry
about tolerance.

00:09:53.090 --> 00:09:57.960
And that means that, in building
a large program,

00:09:57.960 --> 00:10:01.720
there's not all that much
difference between what I can

00:10:01.720 --> 00:10:06.520
build and what I can imagine,
because the parts are these

00:10:06.520 --> 00:10:10.250
abstract entities that I
know as much as I want.

00:10:10.250 --> 00:10:13.430
I know about them as precisely
as I'd like.

00:10:13.430 --> 00:10:15.920
So as opposed to other kinds
of engineering, where the

00:10:15.920 --> 00:10:17.830
constraints on what you can
build are the constraints of

00:10:17.830 --> 00:10:19.810
physical systems, the
constraints of physics and

00:10:19.810 --> 00:10:24.160
noise and approximation, the
constraints imposed in

00:10:24.160 --> 00:10:26.640
building large software systems
are the limitations of

00:10:26.640 --> 00:10:28.930
our own minds.

00:10:28.930 --> 00:10:32.460
So in that sense, computer
science is like an abstract

00:10:32.460 --> 00:10:33.530
form of engineering.

00:10:33.530 --> 00:10:35.680
It's the kind of engineering
where you ignore the

00:10:35.680 --> 00:10:37.645
constraints that are
imposed by reality.

00:10:42.050 --> 00:10:46.400
Well, what are some of
these techniques?

00:10:46.400 --> 00:10:47.830
They're not special to
computer science.

00:10:50.360 --> 00:10:54.140
First technique, which is used
in all of engineering, is a

00:10:54.140 --> 00:10:57.785
kind of abstraction called
black-box abstraction.

00:11:07.670 --> 00:11:14.340
Take something and build
a box about it.

00:11:14.340 --> 00:11:19.220
Let's see, for example, if we
looked at that square root

00:11:19.220 --> 00:11:29.678
method, I might want to take
that and build a box.

00:11:29.678 --> 00:11:38.980
That sort of says, to find the
square root of X. And that

00:11:38.980 --> 00:11:42.560
might be a whole complicated
set of rules.

00:11:42.560 --> 00:11:46.280
And that might end up being a
kind of thing where I can put

00:11:46.280 --> 00:11:50.270
in, say, 36 and say, what's
the square root of 36?

00:11:50.270 --> 00:11:51.520
And out comes six.

00:11:53.880 --> 00:11:59.630
And the important thing is that
I'd like to design that

00:11:59.630 --> 00:12:05.080
so that if George comes along
and would like to compute,

00:12:05.080 --> 00:12:11.580
say, the square root of A plus
the square root of B, he can

00:12:11.580 --> 00:12:14.930
take this thing and use it as
a module without having to

00:12:14.930 --> 00:12:16.760
look inside and build something
that looks like

00:12:16.760 --> 00:12:24.960
this, like an A and a B and a
square root box and another

00:12:24.960 --> 00:12:32.660
square root box and then
something that adds that would

00:12:32.660 --> 00:12:33.870
put out the answer.

00:12:33.870 --> 00:12:38.830
And you can see, just from the
fact that I want to do that,

00:12:38.830 --> 00:12:41.560
is from George's point of view,
the internals of what's

00:12:41.560 --> 00:12:44.170
in here should not
be important.

00:12:44.170 --> 00:12:46.940
So for instance, it shouldn't
matter that, when I wrote

00:12:46.940 --> 00:12:50.750
this, I said I want to find the
square root of X. I could

00:12:50.750 --> 00:12:54.840
have said the square root of Y,
or the square root of A, or

00:12:54.840 --> 00:12:56.890
anything at all.

00:12:56.890 --> 00:13:03.480
That's the fundamental notion of
putting something in a box

00:13:03.480 --> 00:13:07.520
using black-box abstraction
to suppress detail.

00:13:07.520 --> 00:13:10.070
And the reason for that is you
want to go off and build

00:13:10.070 --> 00:13:11.990
bigger boxes.

00:13:11.990 --> 00:13:13.880
Now, there's another reason
for doing black-box

00:13:13.880 --> 00:13:17.340
abstraction other than you want
to suppress detail for

00:13:17.340 --> 00:13:18.310
building bigger boxes.

00:13:18.310 --> 00:13:24.880
Sometimes you want to say that
your way of doing something,

00:13:24.880 --> 00:13:30.210
your how-to method, is an
instance of a more general

00:13:30.210 --> 00:13:33.430
thing, and you'd like your
language to be able to express

00:13:33.430 --> 00:13:35.560
that generality.

00:13:35.560 --> 00:13:37.800
Let me show you another example

00:13:37.800 --> 00:13:38.740
sticking with square roots.

00:13:38.740 --> 00:13:42.260
Let's go back and take another
look at that slide with the

00:13:42.260 --> 00:13:44.380
square root algorithm on it.

00:13:44.380 --> 00:13:45.460
Remember what that says.

00:13:45.460 --> 00:13:50.700
That says, in order to do
something, I make a guess, and

00:13:50.700 --> 00:13:53.800
I improve that guess,
and I sort of keep

00:13:53.800 --> 00:13:56.970
improving that guess.

00:13:56.970 --> 00:13:59.560
So there's the general strategy
of, I'm looking for

00:13:59.560 --> 00:14:02.440
something, and the way
I find it is that I

00:14:02.440 --> 00:14:04.280
keep improving it.

00:14:04.280 --> 00:14:10.930
Now, that's a particular case
of another kind of strategy

00:14:10.930 --> 00:14:14.176
for finding a fixed point
of something.

00:14:14.176 --> 00:14:17.660
So you have a fixed point
of a function.

00:14:17.660 --> 00:14:26.090
A fixed point of a function
is something, is a value.

00:14:26.090 --> 00:14:30.710
A fixed point of a function F is
a value Y, such that F of Y

00:14:30.710 --> 00:14:41.592
equals Y. And the way I might do
that is start with a guess.

00:14:41.592 --> 00:14:44.630
And then if I want something
that doesn't change when I

00:14:44.630 --> 00:14:47.800
keep applying F, is I'll keep
applying F over and over until

00:14:47.800 --> 00:14:50.150
that result doesn't
change very much.

00:14:50.150 --> 00:14:52.290
So there's a general strategy.

00:14:52.290 --> 00:14:56.250
And then, for example, to
compute the square root of X,

00:14:56.250 --> 00:15:00.780
I can try and find a fixed point
of the function which

00:15:00.780 --> 00:15:05.020
takes Y to the average of X/Y.
And the idea that is that if I

00:15:05.020 --> 00:15:09.300
really had Y equal to the square
root of X, then Y and

00:15:09.300 --> 00:15:12.080
X/Y would be the same value.

00:15:12.080 --> 00:15:16.370
They'd both be the square root
of X, because X over the

00:15:16.370 --> 00:15:19.080
square root of X is the
square root of X.

00:15:19.080 --> 00:15:23.860
And so the average if Y were
equal to the square of X, then

00:15:23.860 --> 00:15:26.230
the average wouldn't change.

00:15:26.230 --> 00:15:27.530
So the square root of X
is a fixed point of

00:15:27.530 --> 00:15:30.250
that particular function.

00:15:30.250 --> 00:15:34.010
Now, what I'd like to have,
I'd like to express the

00:15:34.010 --> 00:15:36.430
general strategy for finding
fixed points.

00:15:36.430 --> 00:15:37.210
So what I might imagine doing,
is to find, is to be able to

00:15:37.210 --> 00:15:37.309
use my language to define a box
that says "fixed point,"

00:15:37.309 --> 00:15:37.417
just like I could make a box
that says "square root." And

00:15:37.417 --> 00:15:38.667
I'd like to be able to express
this in my language.

00:15:56.350 --> 00:16:00.870
So I'd like to express not only
the imperative how-to

00:16:00.870 --> 00:16:03.620
knowledge of a particular thing
like square root, but

00:16:03.620 --> 00:16:05.600
I'd like to be able to express
the imperative knowledge of

00:16:05.600 --> 00:16:09.930
how to do a general thing like
how to find fixed point.

00:16:09.930 --> 00:16:12.090
And in fact, let's go back and
look at that slide again.

00:16:15.010 --> 00:16:23.380
See, not only is this a piece
of imperative knowledge, how

00:16:23.380 --> 00:16:27.190
to find a fixed point, but
over here on the bottom,

00:16:27.190 --> 00:16:29.890
there's another piece of
imperative knowledge which

00:16:29.890 --> 00:16:34.350
says, one way to compute square
root is to apply this

00:16:34.350 --> 00:16:36.140
general fixed point method.

00:16:36.140 --> 00:16:37.710
So I'd like to also
be able to express

00:16:37.710 --> 00:16:39.700
that imperative knowledge.

00:16:39.700 --> 00:16:40.650
What would that look like?

00:16:40.650 --> 00:16:46.010
That would say, this fixed point
box is such that if I

00:16:46.010 --> 00:16:56.980
input to it the function that
takes Y to the average of Y

00:16:56.980 --> 00:17:04.300
and X/Y, then what should come
out of that fixed point box is

00:17:04.300 --> 00:17:06.200
a method for finding
square roots.

00:17:08.800 --> 00:17:10.829
So in these boxes we're
building, we're not only

00:17:10.829 --> 00:17:16.369
building boxes that you input
numbers and output numbers,

00:17:16.369 --> 00:17:19.410
we're going to be building in
boxes that, in effect, compute

00:17:19.410 --> 00:17:22.250
methods like finding
square root.

00:17:22.250 --> 00:17:27.480
And my take is their inputs
functions, like Y goes to the

00:17:27.480 --> 00:17:32.360
average of Y and X/Y. The reason
we want to do that, the

00:17:32.360 --> 00:17:35.425
reason this is a procedure, will
end up being a procedure,

00:17:35.425 --> 00:17:39.640
as we'll see, whose value is
another procedure, the reason

00:17:39.640 --> 00:17:42.630
we want to do that is because
procedures are going to be our

00:17:42.630 --> 00:17:47.960
ways of talking about imperative
knowledge.

00:17:47.960 --> 00:17:50.560
And the way to make that very
powerful is to be able to talk

00:17:50.560 --> 00:17:53.260
about other kinds
of knowledge.

00:17:53.260 --> 00:17:55.930
So here is a procedure that, in
effect, talks about another

00:17:55.930 --> 00:17:59.450
procedure, a general strategy
that itself talks about

00:17:59.450 --> 00:18:00.700
general strategies.

00:18:04.290 --> 00:18:08.370
Well, our first topic in this
course-- there'll be three

00:18:08.370 --> 00:18:11.070
major topics-- will be black-box
abstraction.

00:18:11.070 --> 00:18:15.150
Let's look at that in a little
bit more detail.

00:18:15.150 --> 00:18:23.910
What we're going to do is we
will start out talking about

00:18:23.910 --> 00:18:27.480
how Lisp is built up out
of primitive objects.

00:18:27.480 --> 00:18:29.580
What does the language
supply with us?

00:18:29.580 --> 00:18:32.690
And we'll see that there are
primitive procedures and

00:18:32.690 --> 00:18:35.620
primitive data.

00:18:35.620 --> 00:18:38.510
Then we're going to see, how do
you take those primitives

00:18:38.510 --> 00:18:41.940
and combine them to make more
complicated things, means of

00:18:41.940 --> 00:18:42.860
combination?

00:18:42.860 --> 00:18:44.824
And what we'll see is that
there are ways of putting

00:18:44.824 --> 00:18:47.850
things together, putting
primitive procedures together

00:18:47.850 --> 00:18:50.960
to make more complicated
procedures.

00:18:50.960 --> 00:18:53.250
And we'll see how to put
primitive data together to

00:18:53.250 --> 00:18:55.830
make compound data.

00:18:55.830 --> 00:18:59.700
Then we'll say, well, having
made those compounds things,

00:18:59.700 --> 00:19:02.830
how do you abstract them?

00:19:02.830 --> 00:19:05.290
How do you put those black boxes
around them so you can

00:19:05.290 --> 00:19:08.090
use them as components in
more complex things?

00:19:08.090 --> 00:19:11.640
And we'll see that's done by
defining procedures and a

00:19:11.640 --> 00:19:13.740
technique for dealing with
compound data called data

00:19:13.740 --> 00:19:15.540
abstraction.

00:19:15.540 --> 00:19:19.150
And then, what's maybe the most
important thing, is going

00:19:19.150 --> 00:19:21.650
from just the rules to how
does an expert work?

00:19:21.650 --> 00:19:25.800
How do you express common
patterns of doing things, like

00:19:25.800 --> 00:19:28.580
saying, well, there's a general
method of fixed point

00:19:28.580 --> 00:19:32.822
and square root is a particular
case of that?

00:19:32.822 --> 00:19:34.290
And we're going to use--

00:19:34.290 --> 00:19:36.640
I've already hinted at it--
something called higher-order

00:19:36.640 --> 00:19:40.770
procedures, namely procedures
whose inputs and outputs are

00:19:40.770 --> 00:19:43.230
themselves procedures.

00:19:43.230 --> 00:19:44.900
And then we'll also see
something very interesting.

00:19:44.900 --> 00:19:47.730
We'll see, as we go further and
further on and become more

00:19:47.730 --> 00:19:50.310
abstract, there'll be very--

00:19:50.310 --> 00:19:53.700
well, the line between what we
consider to be data and what

00:19:53.700 --> 00:19:56.920
we consider to be procedures
is going to blur at an

00:19:56.920 --> 00:19:58.170
incredible rate.

00:20:03.270 --> 00:20:06.300
Well, that's our first
subject, black-box

00:20:06.300 --> 00:20:07.020
abstraction.

00:20:07.020 --> 00:20:08.270
Let's look at the
second topic.

00:20:10.640 --> 00:20:13.510
I can introduce it like this.

00:20:13.510 --> 00:20:19.590
See, suppose I want to
express the idea--

00:20:19.590 --> 00:20:22.790
remember, we're talking
about ideas--

00:20:22.790 --> 00:20:30.950
suppose I want to express the
idea that I can take something

00:20:30.950 --> 00:20:36.070
and multiply it by the sum
of two other things.

00:20:36.070 --> 00:20:39.720
So for example, I might say,
if I had one and three and

00:20:39.720 --> 00:20:41.920
multiply that by two,
I get eight.

00:20:41.920 --> 00:20:43.930
But I'm talking about the
general idea of what's called

00:20:43.930 --> 00:20:46.470
linear combination, that you
can add two things and

00:20:46.470 --> 00:20:49.170
multiply them by
something else.

00:20:49.170 --> 00:20:51.040
It's very easy when I think
about it for numbers, but

00:20:51.040 --> 00:20:56.060
suppose I also want to use that
same idea to think about,

00:20:56.060 --> 00:21:00.920
I could add two vectors, a1 and
a2, and then scale them by

00:21:00.920 --> 00:21:03.060
some factor x and get
another vector.

00:21:03.060 --> 00:21:08.570
Or I might say, I want to think
about a1 and a2 as being

00:21:08.570 --> 00:21:13.720
polynomials, and I might want
to add those two polynomials

00:21:13.720 --> 00:21:16.680
and then multiply them by two to
get a more complicated one.

00:21:20.020 --> 00:21:24.650
Or a1 and a2 might be electrical
signals, and I

00:21:24.650 --> 00:21:26.870
might want to think about
summing those two electrical

00:21:26.870 --> 00:21:29.350
signals and then putting the
whole thing through an

00:21:29.350 --> 00:21:31.530
amplifier, multiplying
it by some

00:21:31.530 --> 00:21:33.890
factor of two or something.

00:21:33.890 --> 00:21:34.850
The idea is I want to
think about the

00:21:34.850 --> 00:21:38.530
general notion of that.

00:21:38.530 --> 00:21:42.880
Now, if our language is going
to be good language for

00:21:42.880 --> 00:21:47.960
expressing those kind of general
ideas, if I really,

00:21:47.960 --> 00:21:55.190
really can do that, I'd like to
be able to say I'm going to

00:21:55.190 --> 00:22:03.660
multiply by x the sum of a1 and
a2, and I'd like that to

00:22:03.660 --> 00:22:07.470
express the general idea of all
different kinds of things

00:22:07.470 --> 00:22:09.980
that a1 and a2 could be.

00:22:09.980 --> 00:22:11.690
Now, if you think about that,
there's a problem, because

00:22:11.690 --> 00:22:16.370
after all, the actual primitive
operations that go

00:22:16.370 --> 00:22:17.870
on in the machine are obviously
going to be

00:22:17.870 --> 00:22:22.070
different if I'm adding two
numbers than if I'm adding two

00:22:22.070 --> 00:22:25.790
polynomials, or if I'm adding
the representation of two

00:22:25.790 --> 00:22:27.940
electrical signals
or wave forms.

00:22:27.940 --> 00:22:30.950
Somewhere, there has to be the
knowledge of the kinds of

00:22:30.950 --> 00:22:33.140
various things that you
can add and the

00:22:33.140 --> 00:22:34.390
ways of adding them.

00:22:37.110 --> 00:22:39.430
Now, to construct such a system,
the question is, where

00:22:39.430 --> 00:22:41.090
do I put that knowledge?

00:22:41.090 --> 00:22:43.280
How do I think about
the different kinds

00:22:43.280 --> 00:22:44.480
of choices I have?

00:22:44.480 --> 00:22:48.310
And if tomorrow George comes up
with a new kind of object

00:22:48.310 --> 00:22:51.770
that might be added and
multiplied, how do I add

00:22:51.770 --> 00:22:54.280
George's new object to the
system without screwing up

00:22:54.280 --> 00:22:57.690
everything that was
already there?

00:22:57.690 --> 00:23:00.790
Well, that's going to be the
second big topic, the way of

00:23:00.790 --> 00:23:03.720
controlling that kind
of complexity.

00:23:03.720 --> 00:23:07.480
And the way you do that is by
establishing conventional

00:23:07.480 --> 00:23:20.230
interfaces, agreed upon ways of
plugging things together.

00:23:20.230 --> 00:23:23.530
Just like in electrical
engineering, people have

00:23:23.530 --> 00:23:26.520
standard impedances for
connectors, and then you know

00:23:26.520 --> 00:23:28.080
if you build something with
one of those standard

00:23:28.080 --> 00:23:30.160
impedances, you can plug it
together with something else.

00:23:32.720 --> 00:23:34.300
So that's going to be our
second large topic,

00:23:34.300 --> 00:23:35.690
conventional interfaces.

00:23:35.690 --> 00:23:39.000
What we're going to see is,
first, we're going to talk

00:23:39.000 --> 00:23:41.400
about the problem of generic
operations, which is the one I

00:23:41.400 --> 00:23:46.100
alluded to, things like "plus"
that have to work with all

00:23:46.100 --> 00:23:47.350
different kinds of data.

00:23:52.149 --> 00:23:54.660
So we talk about generic
operations.

00:23:54.660 --> 00:23:58.270
Then we're going to talk about
really large-scale structures.

00:23:58.270 --> 00:24:01.820
How do you put together very
large programs that model the

00:24:01.820 --> 00:24:03.880
kinds of complex systems
in the real world that

00:24:03.880 --> 00:24:05.480
you'd like to model?

00:24:05.480 --> 00:24:08.990
And what we're going to see
is that there are two very

00:24:08.990 --> 00:24:11.770
important metaphors for putting
together such systems.

00:24:11.770 --> 00:24:14.730
One is called object-oriented
programming, where you sort of

00:24:14.730 --> 00:24:19.840
think of your system as a kind
of society full of little

00:24:19.840 --> 00:24:21.150
things that interact by sending

00:24:21.150 --> 00:24:23.300
information between them.

00:24:23.300 --> 00:24:26.540
And then the second one is
operations on aggregates,

00:24:26.540 --> 00:24:29.820
called streams, where you think
of a large system put

00:24:29.820 --> 00:24:33.530
together kind of like a signal
processing engineer puts

00:24:33.530 --> 00:24:35.020
together a large electrical
system.

00:24:38.610 --> 00:24:40.240
That's going to be
our second topic.

00:24:43.370 --> 00:24:47.000
Now, the third thing we're going
to come to, the third

00:24:47.000 --> 00:24:49.640
basic technique for controlling
complexity, is

00:24:49.640 --> 00:24:51.680
making new languages.

00:24:51.680 --> 00:24:54.370
Because sometimes, when you're
sort of overwhelmed by the

00:24:54.370 --> 00:24:56.640
complexity of a design, the
way that you control that

00:24:56.640 --> 00:25:01.330
complexity is to pick a
new design language.

00:25:01.330 --> 00:25:03.330
And the purpose of the new
design language will be to

00:25:03.330 --> 00:25:05.730
highlight different aspects
of the system.

00:25:05.730 --> 00:25:08.360
It will suppress some kinds of
details and emphasize other

00:25:08.360 --> 00:25:09.610
kinds of details.

00:25:12.910 --> 00:25:15.910
This is going to be the most
magical part of the course.

00:25:15.910 --> 00:25:18.350
We're going to start out by
actually looking at the

00:25:18.350 --> 00:25:21.730
technology for building new
computer languages.

00:25:21.730 --> 00:25:25.770
The first thing we're going to
do is actually build in Lisp.

00:25:29.210 --> 00:25:32.940
We're going to express in Lisp
the process of interpreting

00:25:32.940 --> 00:25:33.800
Lisp itself.

00:25:33.800 --> 00:25:36.840
And that's going to be a very
sort of self-circular thing.

00:25:36.840 --> 00:25:38.870
There's a little mystical
symbol that

00:25:38.870 --> 00:25:40.750
has to do with that.

00:25:40.750 --> 00:25:45.500
The process of interpreting Lisp
is sort of a giant wheel

00:25:45.500 --> 00:25:49.150
of two processes, apply and
eval, which sort of constantly

00:25:49.150 --> 00:25:52.031
reduce expressions
to each other.

00:25:52.031 --> 00:25:54.150
Then we're going to see all
sorts of other magical things.

00:25:54.150 --> 00:25:56.690
Here's another magical symbol.

00:25:59.870 --> 00:26:02.260
This is sort of the Y operator,
which is, in some

00:26:02.260 --> 00:26:04.800
sense, the expression
of infinity inside

00:26:04.800 --> 00:26:06.390
our procedural language.

00:26:06.390 --> 00:26:08.610
We'll take a look at that.

00:26:08.610 --> 00:26:11.880
In any case, this section
of the course is called

00:26:11.880 --> 00:26:24.270
Metalinguistic Abstraction,
abstracting by talking about

00:26:24.270 --> 00:26:25.535
how you construct
new languages.

00:26:30.270 --> 00:26:34.140
As I said, we're going to start
out by looking at the

00:26:34.140 --> 00:26:35.530
process of interpretation.

00:26:35.530 --> 00:26:38.270
We're going to look
at this apply-eval

00:26:38.270 --> 00:26:41.980
loop, and build Lisp.

00:26:41.980 --> 00:26:44.450
Then, just to show you that this
is very general, we're

00:26:44.450 --> 00:26:47.100
going to use exactly the same
technology to build a very

00:26:47.100 --> 00:26:49.780
different kind of language, a
so-called logic programming

00:26:49.780 --> 00:26:52.880
language, where you don't really
talk about procedures

00:26:52.880 --> 00:26:54.560
at all that have inputs
and outputs.

00:26:54.560 --> 00:26:57.290
What you do is talk about
relations between things.

00:26:57.290 --> 00:27:01.220
And then finally, we're going
to talk about how you

00:27:01.220 --> 00:27:04.140
implement these things very
concretely on the very

00:27:04.140 --> 00:27:06.830
simplest kind of machines.

00:27:06.830 --> 00:27:09.860
We'll see something like this.

00:27:09.860 --> 00:27:14.880
This is a picture of a chip,
which is the Lisp interpreter

00:27:14.880 --> 00:27:17.330
that we will be talking about
then in hardware.

00:27:21.010 --> 00:27:24.840
Well, there's an outline of the
course, three big topics.

00:27:24.840 --> 00:27:28.120
Black-box abstraction,
conventional interfaces,

00:27:28.120 --> 00:27:31.590
metalinguistic abstraction.

00:27:31.590 --> 00:27:33.480
Now, let's take a break now and
then we'll get started.

00:27:33.480 --> 00:28:04.770
[MUSIC PLAYING]

00:28:04.770 --> 00:28:08.020
Let's actually start in
learning Lisp now.

00:28:08.020 --> 00:28:10.250
Actually, we'll start out by
learning something much more

00:28:10.250 --> 00:28:12.320
important, maybe the very most
important thing in this

00:28:12.320 --> 00:28:16.220
course, which is not Lisp, in
particular, of course, but

00:28:16.220 --> 00:28:20.320
rather a general framework for
thinking about languages that

00:28:20.320 --> 00:28:21.970
I already alluded to.

00:28:21.970 --> 00:28:24.420
When somebody tells you they're
going to show you a

00:28:24.420 --> 00:28:27.150
language, what you should say
is, what I'd like you to tell

00:28:27.150 --> 00:28:32.510
me is what are the primitive
elements?

00:28:37.490 --> 00:28:38.930
What does the language
come with?

00:28:38.930 --> 00:28:43.650
Then, what are the ways you
put those together?

00:28:43.650 --> 00:28:46.720
What are the means
of combination?

00:28:50.190 --> 00:28:53.400
What are the things that allow
you to take these primitive

00:28:53.400 --> 00:28:57.920
elements and build bigger
things out of them?

00:28:57.920 --> 00:29:01.280
What are the ways of putting
things together?

00:29:01.280 --> 00:29:04.890
And then, what are the
means of abstraction?

00:29:08.110 --> 00:29:15.830
How do we take those complicated
things and draw

00:29:15.830 --> 00:29:16.750
those boxes around them?

00:29:16.750 --> 00:29:20.180
How do we name them so that we
can now use them as if they

00:29:20.180 --> 00:29:22.810
were primitive elements
in making still

00:29:22.810 --> 00:29:23.790
more complex things?

00:29:23.790 --> 00:29:26.850
And so on, and so
on, and so on.

00:29:26.850 --> 00:29:28.580
So when someone says to you,
gee, I have a great new

00:29:28.580 --> 00:29:32.900
computer language, you don't
say, how many characters does

00:29:32.900 --> 00:29:35.810
it take to invert a matrix?

00:29:35.810 --> 00:29:37.460
It's irrelevant.

00:29:37.460 --> 00:29:41.220
What you say is, if the language
did not come with

00:29:41.220 --> 00:29:43.470
matrices built in or with
something else built in, how

00:29:43.470 --> 00:29:45.910
could I then build that thing?

00:29:45.910 --> 00:29:47.590
What are the means of
combination which would allow

00:29:47.590 --> 00:29:48.610
me to do that?

00:29:48.610 --> 00:29:52.450
And then, what are the means of
abstraction which allow me

00:29:52.450 --> 00:29:55.750
then to use those as elements
in making more complicated

00:29:55.750 --> 00:29:57.000
things yet?

00:29:58.960 --> 00:30:02.330
Well, we're going to see that
Lisp has some primitive data

00:30:02.330 --> 00:30:05.280
and some primitive procedures.

00:30:05.280 --> 00:30:08.410
In fact, let's really start.

00:30:08.410 --> 00:30:09.950
And here's a piece of
primitive data in

00:30:09.950 --> 00:30:16.710
Lisp, number three.

00:30:16.710 --> 00:30:19.070
Actually, if I'm being very
pedantic, that's not the

00:30:19.070 --> 00:30:19.790
number three.

00:30:19.790 --> 00:30:24.620
That's some symbol that
represents Plato's concept of

00:30:24.620 --> 00:30:27.060
the number three.

00:30:27.060 --> 00:30:30.500
And here's another.

00:30:30.500 --> 00:30:35.370
Here's some more primitive
data in Lisp, 17.4.

00:30:35.370 --> 00:30:40.940
Or actually, some representation
of 17.4.

00:30:40.940 --> 00:30:43.795
And here's another one, five.

00:30:46.750 --> 00:30:48.490
Here's another primitive
object that's

00:30:48.490 --> 00:30:52.130
built in Lisp, addition.

00:30:52.130 --> 00:30:56.830
Actually, to use the same kind
of pedantic-- this is a name

00:30:56.830 --> 00:31:00.140
for the primitive method
of adding things.

00:31:00.140 --> 00:31:02.850
Just like this is a name for
Plato's number three, this is

00:31:02.850 --> 00:31:10.370
a name for Plato's concept
of how you add things.

00:31:10.370 --> 00:31:12.370
So those are some primitive
elements.

00:31:12.370 --> 00:31:14.090
I can put them together.

00:31:14.090 --> 00:31:18.140
I can say, gee, what's the sum
of three and 17.4 and five?

00:31:18.140 --> 00:31:25.580
And the way I do that is to
say, let's apply the sum

00:31:25.580 --> 00:31:27.600
operator to these
three numbers.

00:31:27.600 --> 00:31:29.690
And I should get,
what? eight, 17.

00:31:29.690 --> 00:31:34.390
25.4.

00:31:34.390 --> 00:31:37.590
So I should be able to ask Lisp
what the value of this

00:31:37.590 --> 00:31:43.050
is, and it will return 25.4.

00:31:43.050 --> 00:31:44.610
Let's introduce some names.

00:31:44.610 --> 00:31:50.950
This thing that I typed is
called a combination.

00:31:56.830 --> 00:31:59.040
And a combination consists,
in general,

00:31:59.040 --> 00:32:02.790
of applying an operator--

00:32:02.790 --> 00:32:04.220
so this is an operator--

00:32:09.500 --> 00:32:13.190
to some operands.

00:32:13.190 --> 00:32:14.440
These are the operands.

00:32:21.760 --> 00:32:23.640
And of course, I can make
more complex things.

00:32:23.640 --> 00:32:25.950
The reason I can get complexity
out of this is

00:32:25.950 --> 00:32:30.290
because the operands themselves,
in general, can be

00:32:30.290 --> 00:32:31.200
combinations.

00:32:31.200 --> 00:32:37.520
So for instance, I could say,
what is the sum of three and

00:32:37.520 --> 00:32:45.660
the product of five and
six and eight and two?

00:32:45.660 --> 00:32:47.520
And I should get-- let's see--

00:32:47.520 --> 00:32:52.355
30, 40, 43.

00:32:52.355 --> 00:32:56.520
So Lisp should tell
me that that's 43.

00:32:56.520 --> 00:33:01.610
Forming combinations is the
basic needs of combination

00:33:01.610 --> 00:33:04.690
that we'll be looking at.

00:33:04.690 --> 00:33:10.520
And then, well, you see
some syntax here.

00:33:10.520 --> 00:33:16.940
Lisp uses what's called prefix
notation, which means that the

00:33:16.940 --> 00:33:25.400
operator is written to the
left of the operands.

00:33:25.400 --> 00:33:27.810
It's just a convention.

00:33:27.810 --> 00:33:29.960
And notice, it's fully
parenthesized.

00:33:29.960 --> 00:33:32.170
And the parentheses make it
completely unambiguous.

00:33:32.170 --> 00:33:36.840
So by looking at this, I can see
that there's the operator,

00:33:36.840 --> 00:33:42.760
and there are one, two,
three, four operands.

00:33:42.760 --> 00:33:46.980
And I can see that the second
operand here is itself some

00:33:46.980 --> 00:33:52.500
combination that has one
operator and two operands.

00:33:52.500 --> 00:33:55.740
Parentheses in Lisp are a little
bit, or are very unlike

00:33:55.740 --> 00:33:57.630
parentheses in conventional
mathematics.

00:33:57.630 --> 00:34:01.400
In mathematics, we sort of use
them to mean grouping, and it

00:34:01.400 --> 00:34:03.140
sort of doesn't hurt if
sometimes you leave out

00:34:03.140 --> 00:34:04.610
parentheses if people
understand

00:34:04.610 --> 00:34:05.790
that that's a group.

00:34:05.790 --> 00:34:07.660
And in general, it doesn't
hurt if you put in extra

00:34:07.660 --> 00:34:09.760
parentheses, because that
maybe makes the

00:34:09.760 --> 00:34:10.570
grouping more distinct.

00:34:10.570 --> 00:34:13.010
Lisp is not like that.

00:34:13.010 --> 00:34:17.020
In Lisp, you cannot leave out
parentheses, and you cannot

00:34:17.020 --> 00:34:20.530
put in extra parentheses,
because putting in parentheses

00:34:20.530 --> 00:34:23.980
always means, exactly and
precisely, this is a

00:34:23.980 --> 00:34:27.260
combination which has
meaning, applying

00:34:27.260 --> 00:34:29.050
operators to operands.

00:34:29.050 --> 00:34:32.290
And if I left this out, if I
left those parentheses out, it

00:34:32.290 --> 00:34:35.469
would mean something else.

00:34:35.469 --> 00:34:38.100
In fact, the way to think about
this, is really what I'm

00:34:38.100 --> 00:34:42.280
doing when I write something
like this is writing a tree.

00:34:42.280 --> 00:34:47.179
So this combination is a tree
that has a plus and then a

00:34:47.179 --> 00:34:54.500
thee and then a something else
and an eight and a two.

00:34:54.500 --> 00:34:57.670
And then this something else
here is itself a little

00:34:57.670 --> 00:35:03.770
subtree that has a star
and a five and a six.

00:35:03.770 --> 00:35:07.400
And the way to think of that
is, really, what's going on

00:35:07.400 --> 00:35:13.260
are we're writing these trees,
and parentheses are just a way

00:35:13.260 --> 00:35:16.390
to write this two-dimensional
structure as a linear

00:35:16.390 --> 00:35:19.130
character string.

00:35:19.130 --> 00:35:22.110
Because at least when Lisp first
started and people had

00:35:22.110 --> 00:35:24.630
teletypes or punch cards or
whatever, this was more

00:35:24.630 --> 00:35:25.890
convenient.

00:35:25.890 --> 00:35:29.590
Maybe if Lisp started today,
the syntax of Lisp

00:35:29.590 --> 00:35:31.900
would look like that.

00:35:31.900 --> 00:35:33.720
Well, let's look at
what that actually

00:35:33.720 --> 00:35:36.450
looks like on the computer.

00:35:36.450 --> 00:35:39.320
Here I have a Lisp interaction
set up.

00:35:39.320 --> 00:35:41.060
There's a editor.

00:35:41.060 --> 00:35:43.980
And on the top, I'm going to
type some values and ask Lisp

00:35:43.980 --> 00:35:45.050
what they are.

00:35:45.050 --> 00:35:46.750
So for instance, I can say
to Lisp, what's the

00:35:46.750 --> 00:35:49.370
value of that symbol?

00:35:49.370 --> 00:35:50.050
That's three.

00:35:50.050 --> 00:35:51.850
And I ask Lisp to evaluate it.

00:35:51.850 --> 00:35:55.530
And there you see Lisp has
returned on the bottom, and

00:35:55.530 --> 00:35:57.690
said, oh yeah, that's three.

00:35:57.690 --> 00:36:06.490
Or I can say, what's the sum of
three and four and eight?

00:36:06.490 --> 00:36:08.950
What's that combination?

00:36:08.950 --> 00:36:10.660
And ask Lisp to evaluate it.

00:36:14.660 --> 00:36:16.246
That's 15.

00:36:16.246 --> 00:36:19.210
Or I can type in something
more complicated.

00:36:19.210 --> 00:36:27.300
I can say, what's the sum of the
product of three and the

00:36:27.300 --> 00:36:35.210
sum of seven and 19.5?

00:36:35.210 --> 00:36:37.820
And you'll notice here that Lisp
has something built in

00:36:37.820 --> 00:36:39.660
that helps me keep track of
all these parentheses.

00:36:39.660 --> 00:36:42.260
Watch as I type the next closed
parentheses, which is

00:36:42.260 --> 00:36:45.620
going to close the combination
starting with the star.

00:36:45.620 --> 00:36:48.220
The opening one will flash.

00:36:48.220 --> 00:36:50.200
Here, I'll rub those out
and do it again.

00:36:50.200 --> 00:36:53.590
Type close, and you see
that closes the plus.

00:36:53.590 --> 00:36:57.910
Close again, that
closes the star.

00:36:57.910 --> 00:36:59.800
Now I'm back to the sum, and
maybe I'm going to add that

00:36:59.800 --> 00:37:01.480
all to four.

00:37:01.480 --> 00:37:02.630
That closes the plus.

00:37:02.630 --> 00:37:05.750
Now I have a complete
combination, and I can ask

00:37:05.750 --> 00:37:07.170
Lisp for the value of that.

00:37:07.170 --> 00:37:11.310
That kind of paren balancing is
something that's built into

00:37:11.310 --> 00:37:13.630
a lot of Lisp systems to help
you keep track, because it is

00:37:13.630 --> 00:37:16.760
kind of hard just by hand doing
all these parentheses.

00:37:16.760 --> 00:37:20.520
There's another kind of
convention for keeping track

00:37:20.520 --> 00:37:21.100
of parentheses.

00:37:21.100 --> 00:37:24.800
Let me write another complicated
combination.

00:37:24.800 --> 00:37:33.050
Let's take the sum of the
product of three and five and

00:37:33.050 --> 00:37:34.090
add that to something.

00:37:34.090 --> 00:37:37.510
And now what I'm going to do is
I'm going to indent so that

00:37:37.510 --> 00:37:39.830
the operands are written
vertically.

00:37:39.830 --> 00:37:47.250
Which the sum of that and
the product of 47 and--

00:37:47.250 --> 00:37:50.340
let's say the product
of 47 with a

00:37:50.340 --> 00:37:54.520
difference of 20 and 6.8.

00:37:54.520 --> 00:37:58.236
That means subtract
6.8 from 20.

00:37:58.236 --> 00:38:00.050
And then you see the
parentheses close.

00:38:00.050 --> 00:38:01.890
Close the minus.

00:38:01.890 --> 00:38:03.572
Close the star.

00:38:03.572 --> 00:38:05.150
And now let's get another
operator.

00:38:05.150 --> 00:38:08.230
You see the Lisp editor here
is indenting to the right

00:38:08.230 --> 00:38:12.660
position automatically to
help me keep track.

00:38:12.660 --> 00:38:13.920
I'll do that again.

00:38:13.920 --> 00:38:16.220
I'll close that last
parentheses again.

00:38:16.220 --> 00:38:17.470
You see it balances the plus.

00:38:20.340 --> 00:38:24.100
Now I can say, what's
the value of that?

00:38:24.100 --> 00:38:29.620
So those two things, indenting
to the right level, which is

00:38:29.620 --> 00:38:34.230
called pretty printing, and
flashing parentheses, are two

00:38:34.230 --> 00:38:37.120
things that a lot of Lisp
systems have built in to help

00:38:37.120 --> 00:38:37.660
you keep track.

00:38:37.660 --> 00:38:38.910
And you should learn
how to use them.

00:38:42.020 --> 00:38:44.640
Well, those are the
primitives.

00:38:44.640 --> 00:38:46.190
There's a means of
combination.

00:38:46.190 --> 00:38:49.360
Now let's go up to the
means of abstraction.

00:38:49.360 --> 00:38:52.400
I'd like to be able to take
the idea that I do some

00:38:52.400 --> 00:38:54.820
combination like this, and
abstract it and give it a

00:38:54.820 --> 00:38:57.300
simple name, so I can use
that as an element.

00:38:57.300 --> 00:39:01.770
And I do that in Lisp with
"define." So I can say, for

00:39:01.770 --> 00:39:14.515
example, define A to be the
product of five and five.

00:39:17.936 --> 00:39:23.240
And now I could say, for
example, to Lisp, what is the

00:39:23.240 --> 00:39:26.742
product of A and A?

00:39:26.742 --> 00:39:31.980
And this should be 25, and
this should be 625.

00:39:31.980 --> 00:39:36.200
And then, crucial thing,
I can now use A--

00:39:36.200 --> 00:39:38.360
here I've used it in
a combination--

00:39:38.360 --> 00:39:41.770
but I could use that in other
more complicated things that I

00:39:41.770 --> 00:39:43.440
name in turn.

00:39:43.440 --> 00:39:53.970
So I could say, define B to be
the sum of, we'll say, A and

00:39:53.970 --> 00:40:00.260
the product of five and A.
And then close the plus.

00:40:03.470 --> 00:40:04.920
Let's take a look at that
on the computer and

00:40:04.920 --> 00:40:07.850
see how that looks.

00:40:07.850 --> 00:40:10.515
So I'll just type what
I wrote on the board.

00:40:10.515 --> 00:40:21.165
I could say, define A to be the
product of five and five.

00:40:23.675 --> 00:40:25.640
And I'll tell that to Lisp.

00:40:25.640 --> 00:40:27.320
And notice what Lisp responded
there with

00:40:27.320 --> 00:40:29.120
was an A in the bottom.

00:40:29.120 --> 00:40:31.680
In general, when you type in
a definition in Lisp, it

00:40:31.680 --> 00:40:35.180
responds with the symbol
being defined.

00:40:35.180 --> 00:40:39.200
Now I could say to Lisp, what
is the product of A and A?

00:40:42.266 --> 00:40:46.140
And it says that's 625.

00:40:46.140 --> 00:40:59.610
I can define B to be the sum of
A and the product of five

00:40:59.610 --> 00:41:03.110
and A. Close a paren
closes the star.

00:41:03.110 --> 00:41:04.600
Close the plus.

00:41:04.600 --> 00:41:11.030
Close the "define." Lisp says,
OK, B, there on the bottom.

00:41:11.030 --> 00:41:13.110
And now I can say to Lisp,
what's the value of B?

00:41:17.100 --> 00:41:19.310
And I can say something more
complicated, like what's the

00:41:19.310 --> 00:41:26.600
sum of A and the quotient
of B and five?

00:41:26.600 --> 00:41:30.430
That slash is divide, another
primitive operator.

00:41:30.430 --> 00:41:33.830
I've divided B by five,
added it to A. Lisp

00:41:33.830 --> 00:41:36.830
says, OK, that's 55.

00:41:36.830 --> 00:41:39.810
So there's what it looks like.

00:41:39.810 --> 00:41:43.670
There's the basic means
of defining something.

00:41:43.670 --> 00:41:47.870
It's the simplest kind of
naming, but it's not really

00:41:47.870 --> 00:41:49.970
very powerful.

00:41:49.970 --> 00:41:51.760
See, what I'd really
like to name--

00:41:51.760 --> 00:41:53.510
remember, we're talking about
general methods--

00:41:53.510 --> 00:41:56.810
I'd like to name, oh, the
general idea that, for

00:41:56.810 --> 00:42:10.450
example, I could multiply five
by five, or six by six, or

00:42:10.450 --> 00:42:18.240
1,001 by 1,001, 1,001.7
by 1,001.7.

00:42:18.240 --> 00:42:22.350
I'd like to be able to name
the general idea of

00:42:22.350 --> 00:42:23.970
multiplying something
by itself.

00:42:28.400 --> 00:42:28.960
Well, you know what that is.

00:42:28.960 --> 00:42:31.146
That's called squaring.

00:42:31.146 --> 00:42:43.640
And the way I can do that in
Lisp is I can say, define to

00:42:43.640 --> 00:42:57.850
square something x, multiply
x by itself.

00:42:57.850 --> 00:43:01.260
And then having done that,
I could say to Lisp, for

00:43:01.260 --> 00:43:06.240
example, what's the
square of 10?

00:43:06.240 --> 00:43:10.240
And Lisp will say 100.

00:43:10.240 --> 00:43:14.796
So now let's actually look at
that a little more closely.

00:43:14.796 --> 00:43:17.040
Right, there's the definition
of square.

00:43:17.040 --> 00:43:23.730
To square something, multiply
it by itself.

00:43:23.730 --> 00:43:26.210
You see this x here.

00:43:26.210 --> 00:43:28.550
That x is kind of a pronoun,
which is the something that

00:43:28.550 --> 00:43:31.380
I'm going to square.

00:43:31.380 --> 00:43:35.220
And what I do with it
is I multiply x, I

00:43:35.220 --> 00:43:36.930
multiply it by itself.

00:43:44.670 --> 00:43:44.775
OK.

00:43:44.775 --> 00:43:48.280
So there's the notation for
defining a procedure.

00:43:48.280 --> 00:43:52.500
Actually, this is a little bit
confusing, because this is

00:43:52.500 --> 00:43:53.830
sort of how I might
use square.

00:43:53.830 --> 00:43:57.790
And I say square root of x or
square root of 10, but it's

00:43:57.790 --> 00:44:00.300
not making it very clear that
I'm actually naming something.

00:44:02.970 --> 00:44:05.790
So let me write this definition
in another way that

00:44:05.790 --> 00:44:06.770
makes it a little
bit more clear

00:44:06.770 --> 00:44:08.420
that I'm naming something.

00:44:08.420 --> 00:44:28.250
I'll say, "define" square to
be lambda of x times xx.

00:44:36.550 --> 00:44:40.480
Here, I'm naming something
square, just like over here,

00:44:40.480 --> 00:44:44.390
I'm naming something A. The
thing that I'm naming square--

00:44:44.390 --> 00:44:49.290
here, the thing I named A was
the value of this combination.

00:44:49.290 --> 00:44:52.270
Here, the thing that I'm naming
square is this thing

00:44:52.270 --> 00:44:55.610
that begins with lambda, and
lambda is Lisp's way of saying

00:44:55.610 --> 00:44:56.860
make a procedure.

00:45:00.150 --> 00:45:04.170
Let's look at that more
closely on the slide.

00:45:04.170 --> 00:45:07.410
The way I read that definition
is to say, I define square to

00:45:07.410 --> 00:45:09.910
be make a procedure--

00:45:12.730 --> 00:45:14.010
that's what the lambda is--

00:45:14.010 --> 00:45:19.220
make a procedure with
an argument named x.

00:45:19.220 --> 00:45:22.030
And what it does is return
the results of

00:45:22.030 --> 00:45:24.920
multiplying x by itself.

00:45:24.920 --> 00:45:32.380
Now, in general, we're going to
be using this top form of

00:45:32.380 --> 00:45:35.050
defining, just because it's a
little bit more convenient.

00:45:35.050 --> 00:45:38.750
But don't lose sight of the fact
that it's really this.

00:45:38.750 --> 00:45:41.530
In fact, as far as the Lisp
interpreter's concerned,

00:45:41.530 --> 00:45:44.830
there's no difference between
typing this to it and typing

00:45:44.830 --> 00:45:46.460
this to it.

00:45:46.460 --> 00:45:54.380
And there's a word for that,
sort of syntactic sugar.

00:45:54.380 --> 00:45:58.400
What syntactic sugar means,
it's having somewhat more

00:45:58.400 --> 00:46:01.060
convenient surface forms
for typing something.

00:46:01.060 --> 00:46:04.470
So this is just really syntactic
sugar for this

00:46:04.470 --> 00:46:07.310
underlying Greek thing
with the lambda.

00:46:07.310 --> 00:46:09.710
And the reason you should
remember that is don't forget

00:46:09.710 --> 00:46:12.430
that, when I write something
like this, I'm

00:46:12.430 --> 00:46:14.380
really naming something.

00:46:14.380 --> 00:46:17.040
I'm naming something square,
and the something that I'm

00:46:17.040 --> 00:46:21.620
naming square is a procedure
that's getting constructed.

00:46:21.620 --> 00:46:24.820
Well, let's look at that
on the computer, too.

00:46:24.820 --> 00:46:30.660
So I'll come and I'll say,
define square of

00:46:30.660 --> 00:46:34.670
x to be times xx.

00:46:49.570 --> 00:46:53.042
Now I'll tell Lisp that.

00:46:53.042 --> 00:46:56.580
It says "square." See, I've
named something "square." Now,

00:46:56.580 --> 00:47:00.760
having done that, I can
ask Lisp for, what's

00:47:00.760 --> 00:47:05.230
the square of 1,001?

00:47:05.230 --> 00:47:14.920
Or in general, I could say,
what's the square of the sum

00:47:14.920 --> 00:47:17.340
of five and seven?

00:47:22.532 --> 00:47:25.190
The square of 12's 144.

00:47:25.190 --> 00:47:28.080
Or I can use square itself
as an element in some

00:47:28.080 --> 00:47:28.680
combination.

00:47:28.680 --> 00:47:36.420
I can say, what's the sum of
the square of three and the

00:47:36.420 --> 00:47:37.670
square of four?

00:47:42.480 --> 00:47:44.950
nine and 16 is 25.

00:47:44.950 --> 00:47:49.580
Or I can use square as an
element in some much more

00:47:49.580 --> 00:47:50.390
complicated thing.

00:47:50.390 --> 00:47:53.032
I can say, what's the square
of, the sqare of,

00:47:53.032 --> 00:48:07.016
the square of 1,001?

00:48:07.016 --> 00:48:11.160
And there's the square of the
square of the square of 1,001.

00:48:11.160 --> 00:48:15.620
Or I can say to Lisp, what
is square itself?

00:48:15.620 --> 00:48:17.040
What's the value of that?

00:48:17.040 --> 00:48:21.040
And Lisp returns some
conventional way of telling me

00:48:21.040 --> 00:48:22.200
that that's a procedure.

00:48:22.200 --> 00:48:24.990
It says, "compound procedure
square." Remember, the value

00:48:24.990 --> 00:48:30.050
of square is this procedure, and
the thing with the stars

00:48:30.050 --> 00:48:33.810
and the brackets are just Lisp's
conventional way of

00:48:33.810 --> 00:48:37.010
describing that.

00:48:37.010 --> 00:48:40.830
Let's look at two more
examples of defining.

00:48:45.020 --> 00:48:47.210
Here are two more procedures.

00:48:47.210 --> 00:48:51.860
I can define the average of x
and y to be the sum of x and y

00:48:51.860 --> 00:48:54.460
divided by two.

00:48:54.460 --> 00:49:00.830
Or having had average and mean
square, having had average and

00:49:00.830 --> 00:49:03.970
square, I can use that to talk
about the mean square of

00:49:03.970 --> 00:49:08.325
something, which is the average
of the square of x and

00:49:08.325 --> 00:49:10.790
the square of y.

00:49:10.790 --> 00:49:13.870
So for example, having done
that, I could say, what's the

00:49:13.870 --> 00:49:24.915
mean square of two and three?

00:49:24.915 --> 00:49:27.740
And I should get the
average of four and

00:49:27.740 --> 00:49:29.530
nine, which is 6.5.

00:49:32.970 --> 00:49:37.000
The key thing here is that,
having defined square, I can

00:49:37.000 --> 00:49:38.560
use it as if it were
primitive.

00:49:41.410 --> 00:49:45.200
So if we look here on the
slide, if I look at mean

00:49:45.200 --> 00:49:50.910
square, the person defining mean
square doesn't have to

00:49:50.910 --> 00:49:54.660
know, at this point, whether
square was something built

00:49:54.660 --> 00:49:57.540
into the language or
whether it was a

00:49:57.540 --> 00:49:59.600
procedure that was defined.

00:49:59.600 --> 00:50:04.040
And that's a key thing in Lisp,
that you do not make

00:50:04.040 --> 00:50:08.230
arbitrary distinctions between
things that happen to be

00:50:08.230 --> 00:50:10.400
primitive in the language
and things that

00:50:10.400 --> 00:50:12.740
happen to be built in.

00:50:12.740 --> 00:50:14.750
A person using that shouldn't
even have to know.

00:50:14.750 --> 00:50:17.800
So the things you construct get
used with all the power

00:50:17.800 --> 00:50:19.700
and flexibility as if they
were primitives.

00:50:19.700 --> 00:50:21.470
In fact, you can drive that
home by looking on the

00:50:21.470 --> 00:50:24.750
computer one more time.

00:50:24.750 --> 00:50:26.680
We talked about plus.

00:50:26.680 --> 00:50:29.920
And in fact, if I come here on
the computer screen and say,

00:50:29.920 --> 00:50:31.745
what is the value of plus?

00:50:34.380 --> 00:50:36.120
Notice what Lisp types out.

00:50:36.120 --> 00:50:38.230
On the bottom there, it typed
out, "compound procedure

00:50:38.230 --> 00:50:43.070
plus." Because, in this system,
it turns out that the

00:50:43.070 --> 00:50:45.770
addition operator is itself
a compound procedure.

00:50:45.770 --> 00:50:48.140
And if I didn't just type that
in, you'd never know that, and

00:50:48.140 --> 00:50:49.710
it wouldn't make any
difference anyway.

00:50:49.710 --> 00:50:50.240
We don't care.

00:50:50.240 --> 00:50:52.500
It's below the level of
the abstraction that

00:50:52.500 --> 00:50:54.120
we're dealing with.

00:50:54.120 --> 00:50:57.230
So the key thing is you cannot
tell, should not be able to

00:50:57.230 --> 00:51:00.910
tell, in general, the difference
between things that

00:51:00.910 --> 00:51:03.590
are built in and things
that are compound.

00:51:03.590 --> 00:51:04.160
Why is that?

00:51:04.160 --> 00:51:06.630
Because the things that are
compound have an abstraction

00:51:06.630 --> 00:51:09.420
wrapper wrapped around them.

00:51:09.420 --> 00:51:12.510
We've seen almost all the
elements of Lisp now.

00:51:12.510 --> 00:51:15.090
There's only one more we have to
look at, and that is how to

00:51:15.090 --> 00:51:16.510
make a case analysis.

00:51:16.510 --> 00:51:18.760
Let me show you what I mean.

00:51:18.760 --> 00:51:22.550
We might want to think about the
mathematical definition of

00:51:22.550 --> 00:51:23.740
the absolute value functions.

00:51:23.740 --> 00:51:30.520
I might say the absolute value
of x is the function which has

00:51:30.520 --> 00:51:35.670
the property that it's
negative of x.

00:51:35.670 --> 00:51:42.580
For x less than zero, it's
zero for x equal to zero.

00:51:42.580 --> 00:51:46.360
And it's x for x greater
than zero.

00:51:49.190 --> 00:51:51.490
And Lisp has a way of making
case analyses.

00:51:51.490 --> 00:51:55.210
Let me define for you
absolute value.

00:51:55.210 --> 00:52:03.080
Say define the absolute value
of x is conditional.

00:52:03.080 --> 00:52:05.075
This means case analysis,
COND.

00:52:08.773 --> 00:52:18.760
If x is less than zero, the
answer is negate x.

00:52:22.990 --> 00:52:24.290
What I've written here
is a clause.

00:52:29.490 --> 00:52:33.818
This whole thing is a
conditional clause,

00:52:33.818 --> 00:52:36.380
and it has two parts.

00:52:36.380 --> 00:52:44.760
This part here is a predicate
or a condition.

00:52:44.760 --> 00:52:45.640
That's a condition.

00:52:45.640 --> 00:52:47.680
And the condition is expressed
by something called a

00:52:47.680 --> 00:52:51.170
predicate, and a predicate in
Lisp is some sort of thing

00:52:51.170 --> 00:52:53.440
that returns either
true or false.

00:52:53.440 --> 00:52:55.490
And you see Lisp has a
primitive procedure,

00:52:55.490 --> 00:53:00.510
less-than, that tests whether
something is true or false.

00:53:00.510 --> 00:53:06.940
And the other part of a clause
is an action or a thing to do,

00:53:06.940 --> 00:53:07.930
in the case where that's true.

00:53:07.930 --> 00:53:12.130
And here, what I'm doing
is negating x.

00:53:12.130 --> 00:53:13.300
The negation operator, the
minus sign in Lisp is

00:53:13.300 --> 00:53:14.550
a little bit funny.

00:53:17.880 --> 00:53:19.186
If there's two or more
arguments, if there's two

00:53:19.186 --> 00:53:21.740
arguments it subtracts the
second one from the first, and

00:53:21.740 --> 00:53:22.380
we saw that.

00:53:22.380 --> 00:53:25.280
And if there's one argument,
it negates it.

00:53:25.280 --> 00:53:27.700
So this corresponds to that.

00:53:27.700 --> 00:53:28.960
And then there's another
COND clause.

00:53:28.960 --> 00:53:34.630
It says, in the case where
x is equal to zero,

00:53:34.630 --> 00:53:37.482
the answer is zero.

00:53:37.482 --> 00:53:43.480
And in the case where x
is greater than zero,

00:53:43.480 --> 00:53:45.430
the answer is x.

00:53:45.430 --> 00:53:46.790
Close that clause.

00:53:46.790 --> 00:53:48.250
Close the COND.

00:53:48.250 --> 00:53:48.920
Close the definition.

00:53:48.920 --> 00:53:51.110
And there's the definition
of absolute value.

00:53:51.110 --> 00:53:53.560
And you see it's the case
analysis that looks very much

00:53:53.560 --> 00:53:55.265
like the case analysis you
use in mathematics.

00:53:58.500 --> 00:54:02.300
There's a somewhat different
way of writing a restricted

00:54:02.300 --> 00:54:03.090
case analysis.

00:54:03.090 --> 00:54:05.520
Often, you have a case analysis
where you only have

00:54:05.520 --> 00:54:08.810
one case, where you test
something, and then depending

00:54:08.810 --> 00:54:11.000
on whether it's true or false,
you do something.

00:54:11.000 --> 00:54:16.150
And here's another definition of
absolute value which looks

00:54:16.150 --> 00:54:21.010
almost the same, which says,
if x is less than zero, the

00:54:21.010 --> 00:54:24.380
result is negate x.

00:54:24.380 --> 00:54:25.960
Otherwise, the answer is x.

00:54:25.960 --> 00:54:27.120
And we'll be using "if" a lot.

00:54:27.120 --> 00:54:30.650
But again, the thing to remember
is that this form of

00:54:30.650 --> 00:54:35.130
absolute value that you're
looking at here, and then this

00:54:35.130 --> 00:54:37.650
one over here that I wrote
on the board, are

00:54:37.650 --> 00:54:39.040
essentially the same.

00:54:39.040 --> 00:54:40.700
And "if" and COND are--

00:54:40.700 --> 00:54:42.020
well, whichever way
you like it.

00:54:42.020 --> 00:54:45.100
You can think of COND as
syntactic sugar for "if," or

00:54:45.100 --> 00:54:47.375
you can think of "if" as
syntactic sugar for COND, and

00:54:47.375 --> 00:54:48.810
it doesn't make any
difference.

00:54:48.810 --> 00:54:51.400
The person implementing a Lisp
system will pick one and

00:54:51.400 --> 00:54:52.840
implement the other
in terms of that.

00:54:52.840 --> 00:54:54.570
And it doesn't matter
which one you pick.

00:55:02.660 --> 00:55:05.640
Why don't we break now, and
then take some questions.

00:55:05.640 --> 00:55:11.760
How come sometimes when I write
define, I put an open

00:55:11.760 --> 00:55:16.790
paren here and say, define open
paren something or other,

00:55:16.790 --> 00:55:19.480
and sometimes when
I write this, I

00:55:19.480 --> 00:55:22.330
don't put an open paren?

00:55:22.330 --> 00:55:27.550
The answer is, this particular
form of "define," where you

00:55:27.550 --> 00:55:30.850
say define some expression, is
this very special thing for

00:55:30.850 --> 00:55:33.630
defining procedures.

00:55:33.630 --> 00:55:37.900
But again, what it really means
is I'm defining this

00:55:37.900 --> 00:55:41.350
symbol, square, to be that.

00:55:41.350 --> 00:55:44.810
So the way you should think
about it is what "define" does

00:55:44.810 --> 00:55:48.330
is you write "define," and the
second thing you write is the

00:55:48.330 --> 00:55:49.830
symbol here-- no open paren--

00:55:49.830 --> 00:55:54.610
the symbol you're defining and
what you're defining it to be.

00:55:54.610 --> 00:55:57.300
That's like here
and like here.

00:55:57.300 --> 00:56:01.480
That's sort of the basic way
you use "define." And then,

00:56:01.480 --> 00:56:05.040
there's this special syntactic
trick which allows you to

00:56:05.040 --> 00:56:08.140
define procedures that
look like this.

00:56:08.140 --> 00:56:10.690
So the difference is, it's
whether or not you're defining

00:56:10.690 --> 00:56:11.755
a procedure.

00:56:11.755 --> 00:56:38.110
[MUSIC PLAYING]

00:56:38.110 --> 00:56:42.600
Well, believe it or not, you
actually now know enough Lisp

00:56:42.600 --> 00:56:46.610
to write essentially any
numerical procedure that you'd

00:56:46.610 --> 00:56:49.470
write in a language like FORTRAN
or Basic or whatever,

00:56:49.470 --> 00:56:51.656
or, essentially, any
other language.

00:56:51.656 --> 00:56:55.190
And you're probably saying,
that's not believable, because

00:56:55.190 --> 00:56:56.890
you know that these languages
have things like "for

00:56:56.890 --> 00:57:00.910
statements," and "do until
while" or something.

00:57:00.910 --> 00:57:04.745
But we don't really
need any of that.

00:57:04.745 --> 00:57:06.220
In fact, we're not going
to use any of

00:57:06.220 --> 00:57:08.180
that in this course.

00:57:08.180 --> 00:57:10.410
Let me show you.

00:57:10.410 --> 00:57:14.400
Again, looking back at square
root, let's go back to this

00:57:14.400 --> 00:57:18.505
square root algorithm of
Heron of Alexandria.

00:57:18.505 --> 00:57:20.000
Remember what that said.

00:57:20.000 --> 00:57:23.060
It said, to find an
approximation to the square

00:57:23.060 --> 00:57:28.730
root of X, you make a guess,
you improve that guess by

00:57:28.730 --> 00:57:32.900
averaging the guess and
X over the guess.

00:57:32.900 --> 00:57:36.382
You keep improving that until
the guess is good enough.

00:57:36.382 --> 00:57:38.460
I already alluded to the idea.

00:57:38.460 --> 00:57:44.650
The idea is that, if the initial
guess that you took

00:57:44.650 --> 00:57:48.430
was actually equal to the square
root of X, then G here

00:57:48.430 --> 00:57:52.760
would be equal to X/G.

00:57:52.760 --> 00:57:54.400
So if you hit the square
root, averaging them

00:57:54.400 --> 00:57:55.630
wouldn't change it.

00:57:55.630 --> 00:57:59.160
If the G that you picked was
larger than the square root of

00:57:59.160 --> 00:58:03.280
X, then X/G will be smaller than
the square root of X, so

00:58:03.280 --> 00:58:05.890
that when you average
G and X/G, you get

00:58:05.890 --> 00:58:09.130
something in between.

00:58:09.130 --> 00:58:11.790
So if you pick a G that's
too small, your

00:58:11.790 --> 00:58:13.040
answer will be too large.

00:58:13.040 --> 00:58:17.190
If you pick a G that's too
large, if your G is larger

00:58:17.190 --> 00:58:19.420
than the square root of X and
X/G will be smaller than the

00:58:19.420 --> 00:58:21.110
square root of X.

00:58:21.110 --> 00:58:24.460
So averaging always gives you
something in between.

00:58:24.460 --> 00:58:27.450
And then, it's not quite
trivial, but it's possible to

00:58:27.450 --> 00:58:31.050
show that, in fact, if G misses
the square root of X by

00:58:31.050 --> 00:58:34.220
a little bit, the average of G
and X/G will actually keep

00:58:34.220 --> 00:58:37.800
getting closer to the square
root of X. So if you keep

00:58:37.800 --> 00:58:40.140
doing this enough, you'll
eventually get as

00:58:40.140 --> 00:58:41.680
close as you want.

00:58:41.680 --> 00:58:44.170
And then there's another fact,
that you can always start out

00:58:44.170 --> 00:58:49.210
this process by using 1
as an initial guess.

00:58:49.210 --> 00:58:52.440
And it'll always converge to
the square root of X. So

00:58:52.440 --> 00:58:55.610
that's this method of successive
averaging due to

00:58:55.610 --> 00:58:56.660
Heron of Alexandria.

00:58:56.660 --> 00:59:00.250
Let's write it in Lisp.

00:59:00.250 --> 00:59:05.770
Well, the central idea is, what
does it mean to try a

00:59:05.770 --> 00:59:07.940
guess for the square
root of X?

00:59:07.940 --> 00:59:09.780
Let's write that.

00:59:09.780 --> 00:59:24.310
So we'll say, define to try a
guess for the square root of

00:59:24.310 --> 00:59:27.750
X, what do we do?

00:59:27.750 --> 00:59:44.130
We'll say, if the guess is good
enough to be a guess for

00:59:44.130 --> 00:59:48.330
the square root of X,
then, as an answer,

00:59:48.330 --> 00:59:51.550
we'll take the guess.

00:59:51.550 --> 00:59:58.620
Otherwise, we will try
the improved guess.

00:59:58.620 --> 01:00:05.400
We'll improve that guess for
the square root of X, and

01:00:05.400 --> 01:00:09.690
we'll try that as a guess for
the square root of X. Close

01:00:09.690 --> 01:00:13.510
the "try." Close the "if." Close
the "define." So that's

01:00:13.510 --> 01:00:15.820
how we try a guess.

01:00:15.820 --> 01:00:18.050
And then, the next part of the
process said, in order to

01:00:18.050 --> 01:00:28.370
compute square roots, we'll
say, define to compute the

01:00:28.370 --> 01:00:35.290
square root of X, we will try
one as a guess for the square

01:00:35.290 --> 01:00:40.280
root of X. Well, we have to
define a couple more things.

01:00:40.280 --> 01:00:43.770
We have to say, how is
a guess good enough?

01:00:43.770 --> 01:00:45.545
And how do we improve a guess?

01:00:45.545 --> 01:00:47.380
So let's look at that.

01:00:47.380 --> 01:00:53.650
The algorithm to improve a guess
for the square root of

01:00:53.650 --> 01:00:55.640
X, we average--

01:00:55.640 --> 01:00:57.000
that was the algorithm--

01:00:57.000 --> 01:01:00.680
we average the guess with
the quotient of

01:01:00.680 --> 01:01:03.030
dividing X by the guess.

01:01:03.030 --> 01:01:05.810
That's how we improve a guess.

01:01:05.810 --> 01:01:07.720
And to tell whether a guess is
good enough, well, we have to

01:01:07.720 --> 01:01:09.530
decide something.

01:01:09.530 --> 01:01:11.510
This is supposed to be a guess
for the square root of X, so

01:01:11.510 --> 01:01:14.700
one possible thing you can do
is say, when you take that

01:01:14.700 --> 01:01:19.110
guess and square it, do you get
something very close to X?

01:01:19.110 --> 01:01:22.870
So one way to say that is to
say, I square the guess,

01:01:22.870 --> 01:01:26.900
subtract X from that, and see if
the absolute value of that

01:01:26.900 --> 01:01:31.200
whole thing is less than some
small number, which depends on

01:01:31.200 --> 01:01:32.450
my purposes.

01:01:35.080 --> 01:01:40.410
So there's a complete procedure
for how to compute

01:01:40.410 --> 01:01:42.830
the square root of X. Let's look
at the structure of that

01:01:42.830 --> 01:01:44.080
a little bit.

01:01:47.970 --> 01:01:49.100
I have the whole thing.

01:01:49.100 --> 01:01:55.370
I have the notion of how to
compute a square root.

01:01:55.370 --> 01:01:56.960
That's some kind of module.

01:01:56.960 --> 01:01:58.580
That's some kind of black box.

01:01:58.580 --> 01:02:07.340
It's defined in terms of how to
try a guess for the square

01:02:07.340 --> 01:02:09.090
root of X.

01:02:09.090 --> 01:02:15.110
"Try" is defined in terms of,
well, telling whether

01:02:15.110 --> 01:02:16.640
something is good enough
and telling

01:02:16.640 --> 01:02:18.680
how to improve something.

01:02:18.680 --> 01:02:19.800
So good enough.

01:02:19.800 --> 01:02:30.790
"Try" is defined in terms of
"good enough" and "improve."

01:02:30.790 --> 01:02:32.170
And let's see what
else I fill in.

01:02:32.170 --> 01:02:34.640
Well, I'll go down this tree.

01:02:34.640 --> 01:02:36.040
"Good enough" was defined
in terms of

01:02:36.040 --> 01:02:37.930
absolute value, and square.

01:02:40.910 --> 01:02:43.290
And improve was defined in
terms of something called

01:02:43.290 --> 01:02:47.340
averaging and then some other
primitive operator.

01:02:47.340 --> 01:02:49.530
Square root's defined in terms
of "try." "Try" is defined in

01:02:49.530 --> 01:02:53.860
terms of "good enough"
and "improve,"

01:02:53.860 --> 01:02:55.410
but also "try" itself.

01:02:55.410 --> 01:03:02.750
So "try" is also defined in
terms of how to try itself.

01:03:02.750 --> 01:03:06.240
Well, that may give you some
problems. Your high school

01:03:06.240 --> 01:03:10.680
geometry teacher probably told
you that it's naughty to try

01:03:10.680 --> 01:03:13.360
and define things in terms of
themselves, because it doesn't

01:03:13.360 --> 01:03:13.810
make sense.

01:03:13.810 --> 01:03:16.440
But that's false.

01:03:16.440 --> 01:03:18.730
Sometimes it makes perfect
sense to define things in

01:03:18.730 --> 01:03:20.210
terms of themselves.

01:03:20.210 --> 01:03:22.918
And this is the case.

01:03:22.918 --> 01:03:24.150
And we can look at that.

01:03:24.150 --> 01:03:28.140
We could write down what this
means, and say, suppose I

01:03:28.140 --> 01:03:30.100
asked Lisp what the square
root of two is.

01:03:32.690 --> 01:03:35.710
What's the square root
of two mean?

01:03:35.710 --> 01:03:42.700
Well, that means I try one
as a guess for the

01:03:42.700 --> 01:03:43.950
square root of two.

01:03:47.100 --> 01:03:47.760
Now I look.

01:03:47.760 --> 01:03:50.175
I say, gee, is one a good enough
guess for the square

01:03:50.175 --> 01:03:51.140
root of two?

01:03:51.140 --> 01:03:54.140
And that depends on the test
that "good enough" does.

01:03:54.140 --> 01:03:57.010
And in this case, "good enough"
will say, no, one is

01:03:57.010 --> 01:03:59.740
not a good enough guess for
the square root of two.

01:03:59.740 --> 01:04:10.350
So that will reduce to saying,
I have to try an improved--

01:04:10.350 --> 01:04:15.700
improve one as a guess for the
square root of two, and try

01:04:15.700 --> 01:04:19.110
that as a guess for the
square root of two.

01:04:19.110 --> 01:04:22.350
Improving one as a guess for the
square root of two means I

01:04:22.350 --> 01:04:27.270
average one and two
divided by one.

01:04:27.270 --> 01:04:29.550
So this is going
to be average.

01:04:29.550 --> 01:04:37.830
This piece here will be the
average of one and the

01:04:37.830 --> 01:04:40.930
quotient of two by one.

01:04:40.930 --> 01:04:44.910
That's this piece here.

01:04:44.910 --> 01:04:46.160
And this is 1.5.

01:04:49.060 --> 01:04:53.670
So this square root of two
reduces to trying one for the

01:04:53.670 --> 01:05:03.370
square root of two, which
reduces to trying 1.5 as a

01:05:03.370 --> 01:05:06.220
guess for the square
root of two.

01:05:06.220 --> 01:05:07.880
So that makes sense.

01:05:07.880 --> 01:05:09.650
Let's look at the rest
of the process.

01:05:09.650 --> 01:05:14.890
If I try 1.5, that reduces.

01:05:14.890 --> 01:05:18.210
1.5 turns out to be not good
enough as a guess for the

01:05:18.210 --> 01:05:20.130
square root of two.

01:05:20.130 --> 01:05:23.340
So that reduces to trying the
average of 1.5 and two divided

01:05:23.340 --> 01:05:28.200
by 1.5 as a guess for the
square root of two.

01:05:28.200 --> 01:05:31.110
That average turns
out to be 1.333.

01:05:31.110 --> 01:05:34.215
So this whole thing reduces to
trying 1.333 as a guess for

01:05:34.215 --> 01:05:35.130
the square root of two.

01:05:35.130 --> 01:05:37.910
And then so on.

01:05:37.910 --> 01:05:40.750
That reduces to another called
a "good enough," 1.4

01:05:40.750 --> 01:05:41.630
something or other.

01:05:41.630 --> 01:05:45.160
And then it keeps going until
the process finally stops with

01:05:45.160 --> 01:05:47.780
something that "good enough"
thinks is good enough, which,

01:05:47.780 --> 01:05:52.500
in this case, is 1.4142
something or other.

01:05:52.500 --> 01:05:55.890
So the process makes
perfect sense.

01:05:59.710 --> 01:06:02.620
This, by the way, is called
a recursive definition.

01:06:14.410 --> 01:06:19.470
And the ability to make
recursive definitions is a

01:06:19.470 --> 01:06:20.710
source of incredible power.

01:06:20.710 --> 01:06:24.040
And as you can already see I've
hinted at, it's the thing

01:06:24.040 --> 01:06:27.160
that effectively allows you to
do these infinite computations

01:06:27.160 --> 01:06:30.730
that go on until something is
true, without having any other

01:06:30.730 --> 01:06:33.235
constricts other than the
ability to call a procedure.

01:06:35.890 --> 01:06:37.970
Well, let's see, there's
one more thing.

01:06:37.970 --> 01:06:43.210
Let me show you a variant of
this definition of square root

01:06:43.210 --> 01:06:46.300
here on the slide.

01:06:46.300 --> 01:06:48.320
Here's sort of the same thing.

01:06:48.320 --> 01:06:51.430
What I've done here is packaged
the definitions of

01:06:51.430 --> 01:06:55.340
"improve" and "good enough"
and "try" inside "square

01:06:55.340 --> 01:06:59.760
root." So, in effect, what
I've done is I've built a

01:06:59.760 --> 01:07:01.860
square root box.

01:07:01.860 --> 01:07:07.320
So I've built a box that's the
square root procedure that

01:07:07.320 --> 01:07:08.150
someone can use.

01:07:08.150 --> 01:07:11.910
They might put in 36
and get out six.

01:07:11.910 --> 01:07:15.080
And then, packaged inside this
box are the definitions of

01:07:15.080 --> 01:07:26.530
"try" and "good enough"
and "improve."

01:07:26.530 --> 01:07:28.260
So they're hidden
inside this box.

01:07:28.260 --> 01:07:32.010
And the reason for doing that
is that, if someone's using

01:07:32.010 --> 01:07:34.920
this square root, if George is
using this square root, George

01:07:34.920 --> 01:07:39.180
probably doesn't care very much
that, when I implemented

01:07:39.180 --> 01:07:42.600
square root, I had things inside
there called "try" and

01:07:42.600 --> 01:07:48.150
"good enough" and "improve." And
in fact, Harry might have

01:07:48.150 --> 01:07:50.300
a cube root procedure that has
"try" and "good enough" and

01:07:50.300 --> 01:07:53.260
"improve." And in order to not
get the whole system confused,

01:07:53.260 --> 01:07:55.430
it'd be good for Harry to
package his internal

01:07:55.430 --> 01:07:58.320
procedures inside his
cube root procedure.

01:07:58.320 --> 01:08:00.970
Well, this is called block
structure, this particular way

01:08:00.970 --> 01:08:09.940
of packaging internals inside
of a definition.

01:08:09.940 --> 01:08:13.040
And let's go back and look
at the slide again.

01:08:13.040 --> 01:08:17.720
The way to read this kind of
procedure is to say, to define

01:08:17.720 --> 01:08:23.010
"square root," well, inside that
definition, I'll have the

01:08:23.010 --> 01:08:26.479
definition of an "improve" and
the definition of "good

01:08:26.479 --> 01:08:31.149
enough" and the definition of
"try." And then, subject to

01:08:31.149 --> 01:08:36.010
those definitions, the way I do
square root is to try one.

01:08:36.010 --> 01:08:38.310
And notice here, I don't have to
say one as a guess for the

01:08:38.310 --> 01:08:41.290
square root of X, because since
it's all inside the

01:08:41.290 --> 01:08:44.270
square root, it sort of
has this X known.

01:08:54.770 --> 01:08:56.510
Let me summarize.

01:08:56.510 --> 01:08:59.890
We started out with the idea
that what we're going to be

01:08:59.890 --> 01:09:04.960
doing is expressing imperative
knowledge.

01:09:04.960 --> 01:09:08.960
And in fact, here's a slide
that summarizes the way we

01:09:08.960 --> 01:09:09.680
looked at Lisp.

01:09:09.680 --> 01:09:13.609
We started out by looking at
some primitive elements in

01:09:13.609 --> 01:09:17.609
addition and multiplication,
some predicates for testing

01:09:17.609 --> 01:09:19.630
whether something is less-than
or something's equal.

01:09:19.630 --> 01:09:22.330
And in fact, we saw really
sneakily in the system we're

01:09:22.330 --> 01:09:25.160
actually using, these aren't
actually primitives, but it

01:09:25.160 --> 01:09:26.550
doesn't matter.

01:09:26.550 --> 01:09:28.120
What matters is we're going
to use them as if they're

01:09:28.120 --> 01:09:28.510
primitives.

01:09:28.510 --> 01:09:30.220
We're not going to
look inside.

01:09:30.220 --> 01:09:34.540
We also have some primitive
data and some numbers.

01:09:34.540 --> 01:09:36.830
We saw some means of
composition, means of

01:09:36.830 --> 01:09:41.300
combination, the basic one being
composing functions and

01:09:41.300 --> 01:09:44.840
building combinations with
operators and operands.

01:09:44.840 --> 01:09:47.600
And there were some other
things, like COND and "if" and

01:09:47.600 --> 01:09:53.790
"define." But the main thing
about "define," in particular,

01:09:53.790 --> 01:09:55.710
was that it was the means
of abstraction.

01:09:55.710 --> 01:09:57.670
It was the way that
we name things.

01:09:57.670 --> 01:09:59.770
You can also see from this slide
not only where we've

01:09:59.770 --> 01:10:01.450
been, but holes we
have to fill in.

01:10:01.450 --> 01:10:03.930
At some point, we'll have to
talk about how you combine

01:10:03.930 --> 01:10:07.720
primitive data to get compound
data, and how you abstract

01:10:07.720 --> 01:10:11.950
data so you can use large
globs of data as

01:10:11.950 --> 01:10:13.900
if they were primitive.

01:10:13.900 --> 01:10:16.370
So that's where we're going.

01:10:16.370 --> 01:10:20.790
But before we do that, for the
next couple of lectures we're

01:10:20.790 --> 01:10:25.720
going to be talking about, first
of all, how it is that

01:10:25.720 --> 01:10:28.900
you make a link between these
procedures we write and the

01:10:28.900 --> 01:10:32.040
processes that happen
in the machine.

01:10:32.040 --> 01:10:36.210
And then, how it is that you
start using the power of Lisp

01:10:36.210 --> 01:10:38.710
to talk not only about these
individual little

01:10:38.710 --> 01:10:43.080
computations, but about general
conventional methods

01:10:43.080 --> 01:10:45.200
of doing things.

01:10:45.200 --> 01:10:46.730
OK, are there any questions?

01:10:46.730 --> 01:10:47.640
AUDIENCE: Yes.

01:10:47.640 --> 01:10:51.880
If we defined A using
parentheses instead of as we

01:10:51.880 --> 01:10:53.400
did, what would be
the difference?

01:10:53.400 --> 01:10:58.130
PROFESSOR: If I wrote this, if
I wrote that, what I would be

01:10:58.130 --> 01:11:03.740
doing is defining a procedure
named A. In this case, a

01:11:03.740 --> 01:11:07.950
procedure of no arguments,
which, when I ran it, would

01:11:07.950 --> 01:11:10.274
give me back five times five.

01:11:10.274 --> 01:11:10.716
AUDIENCE: Right.

01:11:10.716 --> 01:11:12.610
I mean, you come up with the
same thing, except for you

01:11:12.610 --> 01:11:13.940
really got a different--

01:11:13.940 --> 01:11:14.120
PROFESSOR: Right.

01:11:14.120 --> 01:11:16.330
And the difference would
be, in the old one--

01:11:16.330 --> 01:11:19.180
Let me be a little
bit clearer here.

01:11:19.180 --> 01:11:24.070
Let's call this A, like here.

01:11:24.070 --> 01:11:35.060
And pretend here, just for
contrast, I wrote, define D to

01:11:35.060 --> 01:11:37.300
be the product of
five and five.

01:11:40.200 --> 01:11:42.450
And the difference between
those, let's think about

01:11:42.450 --> 01:11:45.770
interactions with the
Lisp interpreter.

01:11:45.770 --> 01:11:52.860
I could type in A and Lisp
would return 25.

01:11:52.860 --> 01:12:01.240
I could type in D, if I just
typed in D, Lisp would return

01:12:01.240 --> 01:12:08.000
compound procedure D, because
that's what it is.

01:12:08.000 --> 01:12:09.670
It's a procedure.

01:12:09.670 --> 01:12:12.500
I could run D. I could say,
what's the value of running D?

01:12:12.500 --> 01:12:16.520
Here is a combination
with no operands.

01:12:16.520 --> 01:12:17.570
I see there are no operands.

01:12:17.570 --> 01:12:22.940
I didn't put any after D. And
it would say, oh, that's 25.

01:12:22.940 --> 01:12:28.070
Or I could say, just for
completeness, if I typed in,

01:12:28.070 --> 01:12:29.310
what's the value of running A?

01:12:29.310 --> 01:12:31.690
I get an error.

01:12:31.690 --> 01:12:35.150
The error would be the same
one as over there.

01:12:35.150 --> 01:12:40.010
It'd be the error would say,
sorry, 25, which is the value

01:12:40.010 --> 01:12:43.720
of A, is not an operator that
I can apply to something.